diff options
201 files changed, 5773 insertions, 2490 deletions
diff --git a/Android.mk b/Android.mk index d33307425968..ba153ee76b0a 100644 --- a/Android.mk +++ b/Android.mk @@ -87,6 +87,7 @@ $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST): \ frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \ frameworks/base/config/hiddenapi-light-greylist.txt \ frameworks/base/config/hiddenapi-vendor-list.txt \ + frameworks/base/config/hiddenapi-max-sdk-p-blacklist.txt \ frameworks/base/config/hiddenapi-force-blacklist.txt \ $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \ $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \ @@ -98,6 +99,7 @@ $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST): \ --input-greylists \ frameworks/base/config/hiddenapi-light-greylist.txt \ frameworks/base/config/hiddenapi-vendor-list.txt \ + frameworks/base/config/hiddenapi-max-sdk-p-blacklist.txt \ <(comm -12 <(sort $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)) \ $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST)) \ $(PRIVATE_GREYLIST_INPUTS) \ diff --git a/api/current.txt b/api/current.txt index 9269d979104f..0ffa38b6360a 100755 --- a/api/current.txt +++ b/api/current.txt @@ -15407,6 +15407,69 @@ package android.graphics.pdf { } +package android.graphics.text { + + public class LineBreaker { + method public android.graphics.text.LineBreaker.Result computeLineBreaks(android.graphics.text.MeasuredText, android.graphics.text.LineBreaker.ParagraphConstraints, int); + field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2 + field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1 + field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0 + field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2 + field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0 + field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1 + field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1 + field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0 + } + + public static class LineBreaker.Builder { + ctor public LineBreaker.Builder(); + method public android.graphics.text.LineBreaker build(); + method public android.graphics.text.LineBreaker.Builder setBreakStrategy(int); + method public android.graphics.text.LineBreaker.Builder setHyphenationFrequency(int); + method public android.graphics.text.LineBreaker.Builder setIndents(int[]); + method public android.graphics.text.LineBreaker.Builder setJustified(int); + } + + public static class LineBreaker.ParagraphConstraints { + ctor public LineBreaker.ParagraphConstraints(); + method public int getDefaultTabStop(); + method public float getFirstWidth(); + method public int getFirstWidthLineCount(); + method public int[] getTabStops(); + method public float getWidth(); + method public void setIndent(float, int); + method public void setTabStops(int[], int); + method public void setWidth(float); + } + + public static class LineBreaker.Result { + method public float getLineAscent(int); + method public int getLineBreakOffset(int); + method public int getLineCount(); + method public float getLineDescent(int); + method public int getLineHyphenEdit(int); + method public float getLineWidth(int); + method public boolean hasLineTab(int); + } + + public class MeasuredText { + method public void getBounds(int, int, android.graphics.Rect); + method public float getCharWidthAt(int); + method public char[] getChars(); + method public float getWidth(int, int); + } + + public static class MeasuredText.Builder { + ctor public MeasuredText.Builder(char[]); + method public android.graphics.text.MeasuredText.Builder addReplacementRun(android.graphics.Paint, int, int, float); + method public android.graphics.text.MeasuredText.Builder addStyleRun(android.graphics.Paint, int, int, boolean); + method public android.graphics.text.MeasuredText build(); + method public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean); + method public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean); + } + +} + package android.hardware { public deprecated class Camera { @@ -44321,6 +44384,7 @@ package android.text { method public static int lastIndexOf(java.lang.CharSequence, char, int); method public static int lastIndexOf(java.lang.CharSequence, char, int, int); method public static java.lang.CharSequence listEllipsize(android.content.Context, java.util.List<java.lang.CharSequence>, java.lang.String, android.text.TextPaint, float, int); + method public static java.lang.CharSequence makeSafeForPresentation(java.lang.String, int, float, int); method public static boolean regionMatches(java.lang.CharSequence, int, java.lang.CharSequence, int, int); method public static java.lang.CharSequence replace(java.lang.CharSequence, java.lang.String[], java.lang.CharSequence[]); method public static java.lang.String[] split(java.lang.String, java.lang.String); @@ -44332,6 +44396,9 @@ package android.text { field public static final int CAP_MODE_SENTENCES = 16384; // 0x4000 field public static final int CAP_MODE_WORDS = 8192; // 0x2000 field public static final android.os.Parcelable.Creator<java.lang.CharSequence> CHAR_SEQUENCE_CREATOR; + field public static final int SAFE_STRING_FLAG_FIRST_LINE = 4; // 0x4 + field public static final int SAFE_STRING_FLAG_SINGLE_LINE = 2; // 0x2 + field public static final int SAFE_STRING_FLAG_TRIM = 1; // 0x1 } public static abstract interface TextUtils.EllipsizeCallback { @@ -44930,6 +44997,16 @@ package android.text.style { method public abstract void drawBackground(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, int); } + public static class LineBackgroundSpan.Standard implements android.text.style.LineBackgroundSpan android.text.ParcelableSpan { + ctor public LineBackgroundSpan.Standard(int); + ctor public LineBackgroundSpan.Standard(android.os.Parcel); + method public int describeContents(); + method public void drawBackground(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, int); + method public final int getColor(); + method public int getSpanTypeId(); + method public void writeToParcel(android.os.Parcel, int); + } + public abstract interface LineHeightSpan implements android.text.style.ParagraphStyle android.text.style.WrapTogetherSpan { method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt); } diff --git a/api/system-current.txt b/api/system-current.txt index 83a789ad0294..eccc0ea0592a 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -222,7 +222,7 @@ package android { } public static final class R.dimen { - field public static final int config_restricted_icon_size = 17104903; // 0x1050007 + field public static final int config_restrictedIconSize = 17104903; // 0x1050007 } public static final class R.drawable { @@ -235,12 +235,12 @@ package android { } public static final class R.string { - field public static final int config_feedback_intent_extra_key = 17039391; // 0x104001f - field public static final int config_feedback_intent_name_key = 17039392; // 0x1040020 - field public static final int config_help_intent_extra_key = 17039389; // 0x104001d - field public static final int config_help_intent_name_key = 17039390; // 0x104001e - field public static final int config_help_package_name_key = 17039387; // 0x104001b - field public static final int config_help_package_name_value = 17039388; // 0x104001c + field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f + field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020 + field public static final int config_helpIntentExtraKey = 17039389; // 0x104001d + field public static final int config_helpIntentNameKey = 17039390; // 0x104001e + field public static final int config_helpPackageNameKey = 17039387; // 0x104001b + field public static final int config_helpPackageNameValue = 17039388; // 0x104001c } public static final class R.style { @@ -1122,9 +1122,9 @@ package android.content.pm { method public static void forceSafeLabels(); method public deprecated java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager); method public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager, float, int); - field public static final int SAFE_LABEL_FLAG_FIRST_LINE = 4; // 0x4 - field public static final int SAFE_LABEL_FLAG_SINGLE_LINE = 2; // 0x2 - field public static final int SAFE_LABEL_FLAG_TRIM = 1; // 0x1 + field public static final deprecated int SAFE_LABEL_FLAG_FIRST_LINE = 4; // 0x4 + field public static final deprecated int SAFE_LABEL_FLAG_SINGLE_LINE = 2; // 0x2 + field public static final deprecated int SAFE_LABEL_FLAG_TRIM = 1; // 0x1 } public abstract class PackageManager { @@ -1151,7 +1151,8 @@ package android.content.pm { method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle); method public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int); method public void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence); - method public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String); + method public deprecated java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String); + method public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo); method public abstract void setUpdateAvailable(java.lang.String, boolean); method public abstract boolean updateIntentVerificationStatusAsUser(java.lang.String, int, int); method public abstract void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle); @@ -1245,6 +1246,22 @@ package android.content.pm { field public int requestRes; } + public final class SuspendDialogInfo implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.content.pm.SuspendDialogInfo> CREATOR; + } + + public static final class SuspendDialogInfo.Builder { + ctor public SuspendDialogInfo.Builder(); + method public android.content.pm.SuspendDialogInfo build(); + method public android.content.pm.SuspendDialogInfo.Builder setIcon(int); + method public android.content.pm.SuspendDialogInfo.Builder setMessage(java.lang.String); + method public android.content.pm.SuspendDialogInfo.Builder setMessage(int); + method public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonText(int); + method public android.content.pm.SuspendDialogInfo.Builder setTitle(int); + } + } package android.content.pm.dex { @@ -4130,7 +4147,6 @@ package android.os { public class UserManager { method public void clearSeedAccountData(); - method public int[] getProfileIds(int, boolean); method public java.lang.String getSeedAccountName(); method public android.os.PersistableBundle getSeedAccountOptions(); method public java.lang.String getSeedAccountType(); @@ -6650,7 +6666,7 @@ package android.util { package android.view { public abstract class Window { - method public void addPrivateFlags(int); + method public void addSystemFlags(int); } public abstract interface WindowManager implements android.view.ViewManager { @@ -6660,7 +6676,10 @@ package android.view { public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable { method public final long getUserActivityTimeout(); method public final void setUserActivityTimeout(long); - field public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000 + field public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000 + } + + public static abstract class WindowManager.LayoutParams.SystemFlags implements java.lang.annotation.Annotation { } } diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 501b59388aed..46045101f168 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -638,7 +638,7 @@ message WakelockStateChanged { // The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock. // From frameworks/base/core/proto/android/os/enums.proto. - optional android.os.WakeLockLevelEnum level = 2; + optional android.os.WakeLockLevelEnum type = 2; // The wakelock tag (Called tag in the Java API, sometimes name elsewhere). optional string tag = 3; @@ -1031,20 +1031,20 @@ message ResourceConfigurationChanged { // Bit mask of color capabilities of the screen. // Contains information about the color gamut and hdr mode of the screen. // See: https://d.android.com/reference/android/content/res/Configuration.html#colorMode - optional int32 colorMode = 1; + optional int32 color_mode = 1; // The target screen density being rendered to. // See: https://d.android.com/reference/android/content/res/Configuration.html#densityDpi - optional int32 densityDpi = 2; + optional int32 density_dpi = 2; // Current user preference for the scaling factor for fonts, // relative to the base density scaling. // See: https://d.android.com/reference/android/content/res/Configuration.html#fontScale - optional float fontScale = 3; + optional float font_scale = 3; // Flag indicating whether the hard keyboard is hidden. // See: https://d.android.com/reference/android/content/res/Configuration.html#hardKeyboardHidden - optional int32 hardKeyboardHidden = 4; + optional int32 hard_keyboard_hidden = 4; // The type of keyboard attached to the device. // See: https://d.android.com/reference/android/content/res/Configuration.html#keyboard @@ -1052,7 +1052,7 @@ message ResourceConfigurationChanged { // Flag indicating whether any keyboard is available. Takes soft keyboards into account. // See: https://d.android.com/reference/android/content/res/Configuration.html#keyboardHidden - optional int32 keyboardHideen = 6; + optional int32 keyboard_hidden = 6; // IMSI MCC (Mobile Country Code), corresponding to mcc resource qualifier. // 0 if undefined. @@ -1071,7 +1071,7 @@ message ResourceConfigurationChanged { // Flag indicating whether the navigation is available. // See: https://d.android.com/reference/android/content/res/Configuration.html#navigationHidden - optional int32 navigationHidden = 10; + optional int32 navigation_hidden = 10; // Overall orientation of the screen. // See: https://d.android.com/reference/android/content/res/Configuration.html#orientation @@ -1079,24 +1079,24 @@ message ResourceConfigurationChanged { // The current height of the available screen space, in dp units. // See: https://d.android.com/reference/android/content/res/Configuration.html#screenHeightDp - optional int32 screenHeightDp = 12; + optional int32 screen_height_dp = 12; // Bit mask of overall layout of the screen. // Contains information about screen size, whether the screen is wider/taller // than normal, whether the screen layout is right-tl-left or left-to-right, // and whether the screen has a rounded shape. // See: https://d.android.com/reference/android/content/res/Configuration.html#screenLayout - optional int32 screenLayout = 13; + optional int32 screen_layout = 13; // Current width of the available screen space, in dp units. // See: https://d.android.com/reference/android/content/res/Configuration.html#screenWidthDp - optional int32 screenWidthDp = 14; + optional int32 screen_width_dp = 14; // The smallest screen size an application will see in normal operation. // This is the smallest value of both screenWidthDp and screenHeightDp // in portrait and landscape. // See: https://d.android.com/reference/android/content/res/Configuration.html#smallestScreenWidthDp - optional int32 smallestScreenWidthDp = 15; + optional int32 smallest_screen_width_dp = 15; // The type of touch screen attached to the device. // See: https://d.android.com/reference/android/content/res/Configuration.html#touchscreen @@ -1107,7 +1107,7 @@ message ResourceConfigurationChanged { // Eg: NORMAL, DESK, CAR, TELEVISION, WATCH, VR_HEADSET // Also contains information about whether the device is in night mode. // See: https://d.android.com/reference/android/content/res/Configuration.html#uiMode - optional int32 uiMode = 17; + optional int32 ui_mode = 17; } @@ -1194,7 +1194,7 @@ message BluetoothEnabledStateChanged { // Eg. Airplane mode, crash, application request. optional android.bluetooth.EnableDisableReasonEnum reason = 3; // If the reason is an application request, this will be the package name. - optional string pkgName = 4; + optional string pkg_name = 4; } /** @@ -1343,7 +1343,7 @@ message BatteryHealthSnapshot { } optional BatterySnapshotType type = 1; // Temperature, in 1/10ths of degree C. - optional int32 temperature_deci_celcius = 2; + optional int32 temperature_deci_celsius = 2; // Voltage Battery Voltage, in microVolts. optional int32 voltage_micro_volt = 3; // Current Battery current, in microAmps. @@ -1871,10 +1871,10 @@ message AppStartMemoryStateCaptured { optional string activity_name = 3; // # of page-faults - optional int64 pgfault = 4; + optional int64 page_fault = 4; // # of major page-faults - optional int64 pgmajfault = 5; + optional int64 page_major_fault = 5; // RSS optional int64 rss_in_bytes = 6; @@ -1914,13 +1914,13 @@ message LmkKillOccurred { optional string process_name = 2; // oom adj score. - optional int32 oom_score = 3; + optional int32 oom_adj_score = 3; // # of page-faults - optional int64 pgfault = 4; + optional int64 page_fault = 4; // # of major page-faults - optional int64 pgmajfault = 5; + optional int64 page_major_fault = 5; // RSS optional int64 rss_in_bytes = 6; @@ -2182,7 +2182,7 @@ message KernelWakelock { optional int32 version = 3; - optional int64 time = 4; + optional int64 time_micros = 4; } /** @@ -2246,11 +2246,11 @@ message WifiActivityInfo { // stack reported state // TODO: replace this with proto enum optional int32 stack_state = 2; - // tx time in ms + // tx time in millis optional uint64 controller_tx_time_millis = 3; - // rx time in ms + // rx time in millis optional uint64 controller_rx_time_millis = 4; - // idle time in ms + // idle time in millis optional uint64 controller_idle_time_millis = 5; // product of current(mA), voltage(V) and time(ms) optional uint64 controller_energy_used = 6; @@ -2262,9 +2262,9 @@ message WifiActivityInfo { message ModemActivityInfo { // timestamp(wall clock) of record creation optional uint64 timestamp_millis = 1; - // sleep time in ms. + // sleep time in millis. optional uint64 sleep_time_millis = 2; - // idle time in ms + // idle time in millis optional uint64 controller_idle_time_millis = 3; /** * Tx power index @@ -2299,11 +2299,11 @@ message BluetoothActivityInfo { optional uint64 timestamp_millis = 1; // bluetooth stack state optional int32 bluetooth_stack_state = 2; - // tx time in ms + // tx time in millis optional uint64 controller_tx_time_millis = 3; - // rx time in ms + // rx time in millis optional uint64 controller_rx_time_millis = 4; - // idle time in ms + // idle time in millis optional uint64 controller_idle_time_millis = 5; // product of current(mA), voltage(V) and time(ms) optional uint64 energy_used = 6; @@ -2320,13 +2320,13 @@ message ProcessMemoryState { optional string process_name = 2; // oom adj score. - optional int32 oom_score = 3; + optional int32 oom_adj_score = 3; // # of page-faults - optional int64 pgfault = 4; + optional int64 page_fault = 4; // # of major page-faults - optional int64 pgmajfault = 5; + optional int64 page_major_fault = 5; // RSS optional int64 rss_in_bytes = 6; @@ -2408,7 +2408,7 @@ message DiskSpace { * frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp */ message RemainingBatteryCapacity { - optional int32 charge_uAh = 1; + optional int32 charge_micro_ampere_hour = 1; } /** @@ -2417,7 +2417,7 @@ message RemainingBatteryCapacity { * frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp */ message FullBatteryCapacity { - optional int32 capacity_uAh = 1; + optional int32 capacity_micro_ampere_hour = 1; } /** @@ -2427,7 +2427,7 @@ message FullBatteryCapacity { */ message BatteryVoltage { // The voltage of the battery, in millivolts. - optional int32 voltage_mV = 1; + optional int32 voltage_millivolt = 1; } /** @@ -2445,7 +2445,7 @@ message Temperature { optional string sensor_name = 2; // Temperature in tenths of a degree C. - optional int32 temperature_dC = 3; + optional int32 temperature_deci_celsius = 3; } /** @@ -2733,10 +2733,10 @@ message ProcessStatsStateProto { optional android.service.procstats.ProcessState process_state = 3; // Millisecond uptime duration spent in this state - optional int64 duration_ms = 4; + optional int64 duration_millis = 4; // Millisecond elapsed realtime duration spent in this state - optional int64 realtime_duration_ms = 9; + optional int64 realtime_duration_millis = 9; // # of samples taken optional int32 sample_size = 5; @@ -2795,9 +2795,9 @@ message PackageServiceOperationStatsProto { optional android.service.procstats.MemoryState memory_state = 2; // duration in milliseconds. - optional int64 duration_ms = 3; + optional int64 duration_millis = 3; // Millisecond elapsed realtime duration spent in this state - optional int64 realtime_duration_ms = 4; + optional int64 realtime_duration_millis = 4; } repeated StateStats state_stats = 3; } @@ -2821,7 +2821,7 @@ message PackageAssociationSourceProcessStatsProto { optional int32 total_count = 3; // Millisecond uptime total duration this association was around. - optional int64 total_duration_ms = 4; + optional int64 total_duration_millis = 4; // Total count of the times this association became actively impacting its target process. optional int32 active_count = 5; @@ -2831,9 +2831,9 @@ message PackageAssociationSourceProcessStatsProto { // Process state enum. optional android.service.procstats.ProcessState process_state = 1; // Millisecond uptime duration spent in this state - optional int64 duration_ms = 2; + optional int64 duration_millis = 2; // Millisecond elapsed realtime duration spent in this state - optional int64 realtime_duration_ms = 3; + optional int64 realtime_duration_mmillis = 3; } repeated StateStats active_state_stats = 6; } @@ -2868,16 +2868,16 @@ message ProcessStatsPackageProto { message ProcessStatsSectionProto { // Elapsed realtime at start of report. - optional int64 start_realtime_ms = 1; + optional int64 start_realtime_millis = 1; // Elapsed realtime at end of report. - optional int64 end_realtime_ms = 2; + optional int64 end_realtime_millis = 2; // CPU uptime at start of report. - optional int64 start_uptime_ms = 3; + optional int64 start_uptime_millis = 3; // CPU uptime at end of report. - optional int64 end_uptime_ms = 4; + optional int64 end_uptime_millis = 4; // System runtime library. e.g. "libdvm.so", "libart.so". optional string runtime = 5; diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp index 5b6f167984dc..5729febce4e2 100644 --- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp @@ -152,7 +152,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(1).atom_size()); EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, @@ -161,7 +161,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(2).atom_size()); EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size()); @@ -170,7 +170,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(3).atom_size()); EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size()); @@ -179,7 +179,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(3).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(3).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(3).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(4).atom_size()); EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size()); @@ -188,7 +188,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(4).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(4).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(4).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(5).atom_size()); EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size()); @@ -197,7 +197,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(5).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_deci_celsius(), 0); } TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) { @@ -275,7 +275,7 @@ TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(1).atom_size()); EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100, @@ -284,7 +284,7 @@ TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(2, data.bucket_info(2).atom_size()); EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size()); @@ -295,9 +295,9 @@ TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) { EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_TRUE(data.bucket_info(2).atom(1).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(2).atom(1).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(2).atom(1).temperature().temperature_deci_celsius(), 0); } @@ -378,7 +378,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) { EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(1).atom_size()); EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11, @@ -387,7 +387,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) { EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_deci_celsius(), 0); EXPECT_EQ(1, data.bucket_info(2).atom_size()); EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size()); @@ -396,7 +396,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) { EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos()); EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos()); EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty()); - EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0); + EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_deci_celsius(), 0); } diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java index 2b7da6ab6d79..4f4dd011e419 100644 --- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java +++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java @@ -319,7 +319,7 @@ public class MainActivity extends Activity { int[] uids = new int[]{mUids[id]}; String[] tags = new String[]{"acquire"}; StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, - StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name, + StatsLog.WAKELOCK_STATE_CHANGED__TYPE__PARTIAL_WAKE_LOCK, name, StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); StringBuilder sb = new StringBuilder(); sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0) @@ -335,7 +335,7 @@ public class MainActivity extends Activity { int[] uids = new int[]{mUids[id]}; String[] tags = new String[]{"release"}; StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, - StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name, + StatsLog.WAKELOCK_STATE_CHANGED__TYPE__PARTIAL_WAKE_LOCK, name, StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); StringBuilder sb = new StringBuilder(); sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0) diff --git a/cmds/statsd/tools/statsd-testdrive/Android.bp b/cmds/statsd/tools/statsd-testdrive/Android.bp new file mode 100644 index 000000000000..f566bc7f2a53 --- /dev/null +++ b/cmds/statsd/tools/statsd-testdrive/Android.bp @@ -0,0 +1,11 @@ +java_binary_host { + name: "statsd_testdrive", + manifest: "manifest.txt", + srcs: [ + "src/**/*.java", + ], + static_libs: [ + "platformprotos", + "guava", + ], +} diff --git a/cmds/statsd/tools/statsd-testdrive/manifest.txt b/cmds/statsd/tools/statsd-testdrive/manifest.txt new file mode 100644 index 000000000000..0266d1143245 --- /dev/null +++ b/cmds/statsd/tools/statsd-testdrive/manifest.txt @@ -0,0 +1 @@ +Main-class: com.android.statsd.testdrive.TestDrive diff --git a/cmds/statsd/tools/statsd-testdrive/src/com/android/statsd/testdrive/TestDrive.java b/cmds/statsd/tools/statsd-testdrive/src/com/android/statsd/testdrive/TestDrive.java new file mode 100644 index 000000000000..ae3e5a1b1dfa --- /dev/null +++ b/cmds/statsd/tools/statsd-testdrive/src/com/android/statsd/testdrive/TestDrive.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.statsd.testdrive; + +import com.android.internal.os.StatsdConfigProto.AtomMatcher; +import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; +import com.android.internal.os.StatsdConfigProto.StatsdConfig; +import com.android.os.AtomsProto.Atom; +import com.android.os.StatsLog.ConfigMetricsReport; +import com.android.os.StatsLog.ConfigMetricsReportList; + +import com.google.common.io.Files; +import com.google.protobuf.TextFormat; +import com.google.protobuf.TextFormat.ParseException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class TestDrive { + + public static final int PULL_ATOM_START = 10000; + public static final long ATOM_MATCHER_ID = 1234567; + + public static final String UPDATE_CONFIG_CMD = "cmd stats config update"; + public static final String DUMP_REPORT_CMD = "cmd stats dump-report"; + public static final String REMOVE_CONFIG_CMD = "cmd stats config remove"; + public static final String CONFIG_UID = "2000"; // shell uid + public static final long CONFIG_ID = 54321; + + private static boolean mIsPushedAtom = false; + + private static final Logger logger = Logger.getLogger(TestDrive.class.getName()); + + public static void main(String[] args) { + if (args.length != 1) { + logger.log(Level.SEVERE, "Usage: ./test_drive <atomId>"); + return; + } + int atomId; + try { + atomId = Integer.valueOf(args[0]); + } catch (NumberFormatException e) { + logger.log(Level.SEVERE, "Bad atom id provided: " + args[0]); + return; + } + if (Atom.getDescriptor().findFieldByNumber(atomId) == null) { + logger.log(Level.SEVERE, "No such atom found: " + args[0]); + return; + } + mIsPushedAtom = atomId < PULL_ATOM_START; + + TestDrive testDrive = new TestDrive(); + try { + StatsdConfig config = testDrive.createConfig(atomId); + if (config == null) { + logger.log(Level.SEVERE, "Failed to create valid config."); + return; + } + testDrive.pushConfig(config); + logger.info("Pushed the following config to statsd:"); + logger.info(config.toString()); + if (mIsPushedAtom) { + logger.info( + "Now please play with the device to trigger the event. All events should be dumped after 1 min ..."); + Thread.sleep(60_000); + } else { + // wait for 2 min + logger.info("Now wait for 2 minutes ..."); + Thread.sleep(120_000); + } + testDrive.dumpMetrics(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to test drive: " + e.getMessage()); + } finally { + testDrive.removeConfig(); + } + } + + private void pushConfig(StatsdConfig config) throws IOException, InterruptedException { + File configFile = File.createTempFile("statsdconfig", ".config"); + configFile.deleteOnExit(); + Files.write(config.toByteArray(), configFile); + String remotePath = "/data/local/tmp/" + configFile.getName(); + runCommand(null, "adb", "push", configFile.getAbsolutePath(), remotePath); + runCommand( + null, "adb", "shell", "cat", remotePath, "|", UPDATE_CONFIG_CMD, + String.valueOf(CONFIG_ID)); + } + + private void removeConfig() { + try { + runCommand(null, "adb", "shell", REMOVE_CONFIG_CMD, String.valueOf(CONFIG_ID)); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to remove config: " + e.getMessage()); + } + } + + // Runs a shell command. Output should go to outputFile. Returns error string. + private String runCommand(File outputFile, String... commands) + throws IOException, InterruptedException { + // Run macro on target + ProcessBuilder pb = new ProcessBuilder(commands); + // pb.redirectErrorStream(true); + + if (outputFile != null && outputFile.exists() && outputFile.canWrite()) { + pb.redirectOutput(outputFile); + } + Process process = pb.start(); + + // capture any errors + StringBuilder out = new StringBuilder(); + // Read output + BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null, previous = null; + while ((line = br.readLine()) != null) { + if (!line.equals(previous)) { + previous = line; + out.append(line).append('\n'); + logger.fine(line); + } + } + + // Check result + if (process.waitFor() == 0) { + logger.info("Success!"); + } else { + // Abnormal termination: Log command parameters and output and throw ExecutionException + logger.log(Level.SEVERE, out.toString()); + } + return out.toString(); + } + + private StatsdConfig createConfig(int atomId) { + try { + if (mIsPushedAtom) { + return createSimpleEventMetricConfig(atomId); + } else { + return createSimpleGaugeMetricConfig(atomId); + } + } catch (ParseException e) { + logger.log( + Level.SEVERE, + "Failed to parse the config! line: " + + e.getLine() + + " col: " + + e.getColumn() + + " " + + e.getMessage()); + } + return null; + } + + private StatsdConfig createSimpleEventMetricConfig(int atomId) throws ParseException { + StatsdConfig.Builder baseBuilder = getSimpleEventMetricBaseConfig(); + baseBuilder.addAtomMatcher(createAtomMatcher(atomId)); + return baseBuilder.build(); + } + + private StatsdConfig createSimpleGaugeMetricConfig(int atomId) throws ParseException { + StatsdConfig.Builder baseBuilder = getSimpleGaugeMetricBaseConfig(); + baseBuilder.addAtomMatcher(createAtomMatcher(atomId)); + return baseBuilder.build(); + } + + private AtomMatcher createAtomMatcher(int atomId) { + AtomMatcher.Builder atomMatcherBuilder = AtomMatcher.newBuilder(); + atomMatcherBuilder + .setId(ATOM_MATCHER_ID) + .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder().setAtomId(atomId)); + return atomMatcherBuilder.build(); + } + + private StatsdConfig.Builder getSimpleEventMetricBaseConfig() throws ParseException { + StatsdConfig.Builder builder = StatsdConfig.newBuilder(); + TextFormat.merge(EVENT_BASE_CONFIG_SRTR, builder); + return builder; + } + + private StatsdConfig.Builder getSimpleGaugeMetricBaseConfig() throws ParseException { + StatsdConfig.Builder builder = StatsdConfig.newBuilder(); + TextFormat.merge(GAUGE_BASE_CONFIG_STR, builder); + return builder; + } + + private ConfigMetricsReportList getReportList() throws Exception { + try { + File outputFile = File.createTempFile("statsdret", ".bin"); + outputFile.deleteOnExit(); + runCommand( + outputFile, + "adb", + "shell", + DUMP_REPORT_CMD, + String.valueOf(CONFIG_ID), + "--include_current_bucket", + "--proto"); + ConfigMetricsReportList reportList = + ConfigMetricsReportList.parseFrom(new FileInputStream(outputFile)); + return reportList; + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + logger.log( + Level.SEVERE, + "Failed to fetch and parse the statsd output report. " + + "Perhaps there is not a valid statsd config for the requested " + + "uid=" + + CONFIG_UID + + ", id=" + + CONFIG_ID + + "."); + throw (e); + } + } + + private void dumpMetrics() throws Exception { + ConfigMetricsReportList reportList = getReportList(); + // We may get multiple reports. Take the last one. + ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1); + // Really should be only one metric. + if (report.getMetricsCount() != 1) { + logger.log(Level.SEVERE, "Only one report metric expected, got " + + report.getMetricsCount()); + return; + } + + logger.info("Got following metric data dump:"); + logger.info(report.getMetrics(0).toString()); + } + + private static final String EVENT_BASE_CONFIG_SRTR = + "id: 12345\n" + + "event_metric {\n" + + " id: 1111\n" + + " what: 1234567\n" + + "}\n" + + "allowed_log_source: \"AID_GRAPHICS\"\n" + + "allowed_log_source: \"AID_INCIDENTD\"\n" + + "allowed_log_source: \"AID_STATSD\"\n" + + "allowed_log_source: \"AID_RADIO\"\n" + + "allowed_log_source: \"com.android.systemui\"\n" + + "allowed_log_source: \"com.android.vending\"\n" + + "allowed_log_source: \"AID_SYSTEM\"\n" + + "allowed_log_source: \"AID_ROOT\"\n" + + "allowed_log_source: \"AID_BLUETOOTH\"\n" + + "\n" + + "hash_strings_in_metric_report: false"; + + private static final String GAUGE_BASE_CONFIG_STR = + "id: 56789\n" + + "gauge_metric {\n" + + " id: 2222\n" + + " what: 1234567\n" + + " gauge_fields_filter {\n" + + " include_all: true\n" + + " }\n" + + " bucket: ONE_MINUTE\n" + + "}\n" + + "allowed_log_source: \"AID_GRAPHICS\"\n" + + "allowed_log_source: \"AID_INCIDENTD\"\n" + + "allowed_log_source: \"AID_STATSD\"\n" + + "allowed_log_source: \"AID_RADIO\"\n" + + "allowed_log_source: \"com.android.systemui\"\n" + + "allowed_log_source: \"com.android.vending\"\n" + + "allowed_log_source: \"AID_SYSTEM\"\n" + + "allowed_log_source: \"AID_ROOT\"\n" + + "allowed_log_source: \"AID_BLUETOOTH\"\n" + + "\n" + + "hash_strings_in_metric_report: false"; +} diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index b71274cf5dc2..857c39045085 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -2791,16 +2791,6 @@ Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ss Ljavax/net/ssl/SSLSocketFactory;->createSocket(Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket; Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory; Llibcore/icu/ICU;->addLikelySubtags(Ljava/util/Locale;)Ljava/util/Locale; -Llibcore/io/Libcore;->os:Llibcore/io/Os; -Llibcore/io/Memory;->peekByte(J)B -Llibcore/io/Memory;->peekByteArray(J[BII)V -Llibcore/io/Memory;->peekInt(JZ)I -Llibcore/io/Memory;->peekLong(JZ)J -Llibcore/io/Memory;->pokeByte(JB)V -Llibcore/io/Memory;->pokeByteArray(J[BII)V -Llibcore/io/Memory;->pokeInt(JIZ)V -Llibcore/io/Memory;->pokeLong(JJZ)V -Llibcore/io/Streams;->copy(Ljava/io/InputStream;Ljava/io/OutputStream;)I Llibcore/util/BasicLruCache;->map:Ljava/util/LinkedHashMap; Llibcore/util/ZoneInfo;->mTransitions:[J Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String; diff --git a/config/hiddenapi-max-sdk-p-blacklist.txt b/config/hiddenapi-max-sdk-p-blacklist.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/config/hiddenapi-max-sdk-p-blacklist.txt diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 784ce04908fe..296c063f5379 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -22,6 +22,7 @@ import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.IIntentSender; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.UserInfo; import android.os.Bundle; @@ -242,4 +243,10 @@ public abstract class ActivityManagerInternal { throws TransactionTooLargeException; public abstract void disconnectActivityFromServices(Object connectionHolder); + public abstract void cleanUpServices(int userId, ComponentName component, Intent baseIntent); + public abstract ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId); + public abstract void ensureBootCompleted(); + public abstract void updateOomLevelsForDisplay(int displayId); + public abstract boolean isActivityStartsLoggingEnabled(); + public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing); } diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java index af8aa4e7c3b4..b8fe2f13d328 100644 --- a/core/java/android/app/ActivityTaskManager.java +++ b/core/java/android/app/ActivityTaskManager.java @@ -45,6 +45,12 @@ public class ActivityTaskManager { public static final int INVALID_STACK_ID = -1; /** + * Invalid task ID. + * @hide + */ + public static final int INVALID_TASK_ID = -1; + + /** * Parameter to {@link IActivityTaskManager#setTaskWindowingModeSplitScreenPrimary} which * specifies the position of the created docked stack at the top half of the screen if * in portrait mode or at the left half of the screen if in landscape mode. diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index ff6aca6fa6c4..9d3c5c6417af 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5054,7 +5054,7 @@ public final class ActivityThread extends ClientTransactionHandler { private void performConfigurationChangedForActivity(ActivityClientRecord r, Configuration newBaseConfig) { performConfigurationChangedForActivity(r, newBaseConfig, - r.activity.getDisplay().getDisplayId(), false /* movedToDifferentDisplay */); + r.activity.getDisplayId(), false /* movedToDifferentDisplay */); } /** @@ -5406,7 +5406,7 @@ public final class ActivityThread extends ClientTransactionHandler { return; } final boolean movedToDifferentDisplay = displayId != INVALID_DISPLAY - && displayId != r.activity.getDisplay().getDisplayId(); + && displayId != r.activity.getDisplayId(); // Perform updates. r.overrideConfig = overrideConfig; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index a05d01b5ad9a..a30ae799bd3d 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -431,9 +431,11 @@ public class AppOpsManager { public static final int OP_BLUETOOTH_SCAN = 77; /** @hide Use the BiometricPrompt/BiometricManager APIs. */ public static final int OP_USE_BIOMETRIC = 78; + /** @hide Physical activity recognition. */ + public static final int OP_ACTIVITY_RECOGNITION = 79; /** @hide */ @UnsupportedAppUsage - public static final int _NUM_OP = 79; + public static final int _NUM_OP = 80; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -681,6 +683,9 @@ public class AppOpsManager { /** @hide Use the BiometricPrompt/BiometricManager APIs. */ public static final String OPSTR_USE_BIOMETRIC = "android:use_biometric"; + /** @hide Recognize physical activity. */ + public static final String OPSTR_ACTIVITY_RECOGNITION = "android:activity_recognition"; + // Warning: If an permission is added here it also has to be added to // com.android.packageinstaller.permission.utils.EventLogger private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = { @@ -722,6 +727,8 @@ public class AppOpsManager { OP_CAMERA, // Body sensors OP_BODY_SENSORS, + // Activity recognition + OP_ACTIVITY_RECOGNITION, // APPOP PERMISSIONS OP_ACCESS_NOTIFICATIONS, @@ -819,6 +826,7 @@ public class AppOpsManager { OP_START_FOREGROUND, // START_FOREGROUND OP_COARSE_LOCATION, // BLUETOOTH_SCAN OP_USE_BIOMETRIC, // BIOMETRIC + OP_ACTIVITY_RECOGNITION, // ACTIVITY_RECOGNITION }; /** @@ -904,6 +912,7 @@ public class AppOpsManager { OPSTR_START_FOREGROUND, OPSTR_BLUETOOTH_SCAN, OPSTR_USE_BIOMETRIC, + OPSTR_ACTIVITY_RECOGNITION, }; /** @@ -990,6 +999,7 @@ public class AppOpsManager { "START_FOREGROUND", "BLUETOOTH_SCAN", "USE_BIOMETRIC", + "ACTIVITY_RECOGNITION", }; /** @@ -1077,6 +1087,7 @@ public class AppOpsManager { Manifest.permission.FOREGROUND_SERVICE, null, // no permission for OP_BLUETOOTH_SCAN Manifest.permission.USE_BIOMETRIC, + Manifest.permission.ACTIVITY_RECOGNITION, }; /** @@ -1164,6 +1175,7 @@ public class AppOpsManager { null, // START_FOREGROUND null, // maybe should be UserManager.DISALLOW_SHARE_LOCATION, //BLUETOOTH_SCAN null, // USE_BIOMETRIC + null, // ACTIVITY_RECOGNITION }; /** @@ -1250,6 +1262,7 @@ public class AppOpsManager { false, // START_FOREGROUND true, // BLUETOOTH_SCAN false, // USE_BIOMETRIC + false, // ACTIVITY_RECOGNITION }; /** @@ -1335,6 +1348,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // START_FOREGROUND AppOpsManager.MODE_ALLOWED, // BLUETOOTH_SCAN AppOpsManager.MODE_ALLOWED, // USE_BIOMETRIC + AppOpsManager.MODE_ALLOWED, // ACTIVITY_RECOGNITION }; /** @@ -1424,6 +1438,7 @@ public class AppOpsManager { false, // START_FOREGROUND false, // BLUETOOTH_SCAN false, // USE_BIOMETRIC + false, // ACTIVITY_RECOGNITION }; /** diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 264029b6ace7..fcd9a0511265 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -55,6 +55,7 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; +import android.content.pm.SuspendDialogInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; @@ -85,6 +86,7 @@ import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructStat; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.IconDrawableFactory; import android.util.LauncherIcons; @@ -2255,9 +2257,19 @@ public class ApplicationPackageManager extends PackageManager { public String[] setPackagesSuspended(String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage) { + final SuspendDialogInfo dialogInfo = !TextUtils.isEmpty(dialogMessage) + ? new SuspendDialogInfo.Builder().setMessage(dialogMessage).build() + : null; + return setPackagesSuspended(packageNames, suspended, appExtras, launcherExtras, dialogInfo); + } + + @Override + public String[] setPackagesSuspended(String[] packageNames, boolean suspended, + PersistableBundle appExtras, PersistableBundle launcherExtras, + SuspendDialogInfo dialogInfo) { try { return mPM.setPackagesSuspendedAsUser(packageNames, suspended, appExtras, - launcherExtras, dialogMessage, mContext.getOpPackageName(), + launcherExtras, dialogInfo, mContext.getOpPackageName(), getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 77f639535b15..dc707e892d9a 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2088,8 +2088,7 @@ class ContextImpl extends Context { ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, new UserHandle(UserHandle.getUserId(application.uid)), flags, null); - final int displayId = mDisplay != null - ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; + final int displayId = getDisplayId(); c.setResources(createResources(mActivityToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); @@ -2124,8 +2123,7 @@ class ContextImpl extends Context { ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user, flags, null); - final int displayId = mDisplay != null - ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; + final int displayId = getDisplayId(); c.setResources(createResources(mActivityToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); @@ -2152,8 +2150,7 @@ class ContextImpl extends Context { final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName, mActivityToken, mUser, mFlags, classLoader); - final int displayId = mDisplay != null - ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; + final int displayId = getDisplayId(); context.setResources(ResourcesManager.getInstance().getResources( mActivityToken, @@ -2177,7 +2174,7 @@ class ContextImpl extends Context { ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, mFlags, mClassLoader); - final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; + final int displayId = getDisplayId(); context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo())); return context; @@ -2250,6 +2247,11 @@ class ContextImpl extends Context { } @Override + public int getDisplayId() { + return mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; + } + + @Override public void updateDisplay(int displayId) { mDisplay = mResourcesManager.getAdjustedDisplay(displayId, mResources); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index b57a7d982960..4f41da6e52fb 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -20,6 +20,7 @@ import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast; import android.annotation.ColorInt; import android.annotation.DrawableRes; +import android.annotation.IdRes; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -37,6 +38,7 @@ import android.content.pm.ShortcutInfo; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -7759,8 +7761,17 @@ public class Notification implements Parcelable * @see Notification.Builder#setColorized(boolean) */ public static class MediaStyle extends Style { + // Changing max media buttons requires also changing templates + // (notification_template_material_media and notification_template_material_big_media). static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3; static final int MAX_MEDIA_BUTTONS = 5; + @IdRes private static final int[] MEDIA_BUTTON_IDS = { + R.id.action0, + R.id.action1, + R.id.action2, + R.id.action3, + R.id.action4, + }; private int[] mActionsToShowInCompact = null; private MediaSession.Token mToken; @@ -7874,15 +7885,16 @@ public class Notification implements Parcelable return false; } - private RemoteViews generateMediaActionButton(Action action, int color) { + private void bindMediaActionButton(RemoteViews container, @IdRes int buttonId, + Action action, int color) { final boolean tombstone = (action.actionIntent == null); - RemoteViews button = new BuilderRemoteViews(mBuilder.mContext.getApplicationInfo(), - R.layout.notification_material_media_action); - button.setImageViewIcon(R.id.action0, action.getIcon()); + container.setViewVisibility(buttonId, View.VISIBLE); + container.setImageViewIcon(buttonId, action.getIcon()); // If the action buttons should not be tinted, then just use the default // notification color. Otherwise, just use the passed-in color. - Configuration currentConfig = mBuilder.mContext.getResources().getConfiguration(); + Resources resources = mBuilder.mContext.getResources(); + Configuration currentConfig = resources.getConfiguration(); boolean inNightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; int tintColor = mBuilder.shouldTintActionButtons() || mBuilder.isColorized() @@ -7890,13 +7902,21 @@ public class Notification implements Parcelable : ContrastColorUtil.resolveColor(mBuilder.mContext, Notification.COLOR_DEFAULT, inNightMode); - button.setDrawableTint(R.id.action0, false, tintColor, + container.setDrawableTint(buttonId, false, tintColor, PorterDuff.Mode.SRC_ATOP); + + final TypedArray typedArray = mBuilder.mContext.obtainStyledAttributes( + new int[]{ android.R.attr.colorControlHighlight }); + int rippleAlpha = Color.alpha(typedArray.getColor(0, 0)); + typedArray.recycle(); + int rippleColor = Color.argb(rippleAlpha, Color.red(tintColor), Color.green(tintColor), + Color.blue(tintColor)); + container.setRippleDrawableColor(buttonId, ColorStateList.valueOf(rippleColor)); + if (!tombstone) { - button.setOnClickPendingIntent(R.id.action0, action.actionIntent); + container.setOnClickPendingIntent(buttonId, action.actionIntent); } - button.setContentDescription(R.id.action0, action.title); - return button; + container.setContentDescription(buttonId, action.title); } private RemoteViews makeMediaContentView() { @@ -7905,21 +7925,20 @@ public class Notification implements Parcelable null /* result */); final int numActions = mBuilder.mActions.size(); - final int N = mActionsToShowInCompact == null + final int numActionsToShow = mActionsToShowInCompact == null ? 0 : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT); - view.removeAllViews(com.android.internal.R.id.media_actions); - if (N > 0) { - for (int i = 0; i < N; i++) { - if (i >= numActions) { - throw new IllegalArgumentException(String.format( - "setShowActionsInCompactView: action %d out of bounds (max %d)", - i, numActions - 1)); - } - + if (numActionsToShow > numActions) { + throw new IllegalArgumentException(String.format( + "setShowActionsInCompactView: action %d out of bounds (max %d)", + numActions, numActions - 1)); + } + for (int i = 0; i < MAX_MEDIA_BUTTONS_IN_COMPACT; i++) { + if (i < numActionsToShow) { final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]); - final RemoteViews button = generateMediaActionButton(action, getActionColor()); - view.addView(com.android.internal.R.id.media_actions, button); + bindMediaActionButton(view, MEDIA_BUTTON_IDS[i], action, getActionColor()); + } else { + view.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE); } } handleImage(view); @@ -7949,12 +7968,12 @@ public class Notification implements Parcelable RemoteViews big = mBuilder.applyStandardTemplate( R.layout.notification_template_material_big_media, false, null /* result */); - if (actionCount > 0) { - big.removeAllViews(com.android.internal.R.id.media_actions); - for (int i = 0; i < actionCount; i++) { - final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i), + for (int i = 0; i < MAX_MEDIA_BUTTONS; i++) { + if (i < actionCount) { + bindMediaActionButton(big, MEDIA_BUTTON_IDS[i], mBuilder.mActions.get(i), getActionColor()); - big.addView(com.android.internal.R.id.media_actions, button); + } else { + big.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE); } } handleImage(big); diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 0044005c51f2..77cebc8f408d 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -377,11 +377,15 @@ final class SystemServiceRegistry { return new DisplayManager(ctx.getOuterContext()); }}); + // InputMethodManager has its own cache strategy based on display id to support apps that + // still assume InputMethodManager is a per-process singleton and it's safe to directly + // access internal fields via reflection. Hence directly use ServiceFetcher instead of + // StaticServiceFetcher/CachedServiceFetcher. registerService(Context.INPUT_METHOD_SERVICE, InputMethodManager.class, - new StaticServiceFetcher<InputMethodManager>() { + new ServiceFetcher<InputMethodManager>() { @Override - public InputMethodManager createService() { - return InputMethodManager.getInstanceInternal(); + public InputMethodManager getService(ContextImpl ctx) { + return InputMethodManager.forContext(ctx.getOuterContext()); }}); registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index db4adcfaaf35..31973524ceaf 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4982,6 +4982,14 @@ public abstract class Context { public abstract Display getDisplay(); /** + * Gets the display ID. + * + * @return display ID associated with this {@link Context}. + * @hide + */ + public abstract int getDisplayId(); + + /** * @hide */ public abstract void updateDisplay(int displayId); diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index c5dce017430b..bfad2b42bc94 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -921,6 +921,14 @@ public class ContextWrapper extends Context { * @hide */ @Override + public int getDisplayId() { + return mBase.getDisplayId(); + } + + /** + * @hide + */ + @Override public void updateDisplay(int displayId) { mBase.updateDisplay(displayId); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 6a20c9349e1d..4a4de5160e80 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -43,6 +43,7 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VersionedPackage; @@ -273,7 +274,7 @@ interface IPackageManager { String[] setPackagesSuspendedAsUser(in String[] packageNames, boolean suspended, in PersistableBundle appExtras, in PersistableBundle launcherExtras, - String dialogMessage, String callingPackage, int userId); + in SuspendDialogInfo dialogInfo, String callingPackage, int userId); boolean isPackageSuspendedForUser(String packageName, int userId); diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index 00aa5c291154..cdb781438909 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -16,10 +16,12 @@ package android.content.pm; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static android.text.TextUtils.SAFE_STRING_FLAG_FIRST_LINE; +import static android.text.TextUtils.SAFE_STRING_FLAG_SINGLE_LINE; +import static android.text.TextUtils.SAFE_STRING_FLAG_TRIM; +import static android.text.TextUtils.makeSafeForPresentation; import android.annotation.FloatRange; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.res.XmlResourceParser; @@ -27,17 +29,13 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcel; import android.os.UserHandle; -import android.text.Html; -import android.text.TextPaint; import android.text.TextUtils; import android.util.Printer; import android.util.proto.ProtoOutputStream; import com.android.internal.util.Preconditions; -import java.lang.annotation.Retention; import java.text.Collator; -import java.util.BitSet; import java.util.Comparator; /** @@ -50,9 +48,6 @@ import java.util.Comparator; * in the implementation of Parcelable in subclasses. */ public class PackageItemInfo { - private static final int LINE_FEED_CODE_POINT = 10; - private static final int NBSP_CODE_POINT = 160; - /** The maximum length of a safe label, in characters */ private static final int MAX_SAFE_LABEL_LENGTH = 50000; @@ -60,45 +55,43 @@ public class PackageItemInfo { public static final float DEFAULT_MAX_LABEL_SIZE_PX = 500f; /** - * Flags for {@link #loadSafeLabel(PackageManager, float, int)} - * - * @hide - */ - @Retention(SOURCE) - @IntDef(flag = true, prefix = "SAFE_LABEL_FLAG_", - value = {SAFE_LABEL_FLAG_TRIM, SAFE_LABEL_FLAG_SINGLE_LINE, - SAFE_LABEL_FLAG_FIRST_LINE}) - public @interface SafeLabelFlags {} - - /** * Remove {@link Character#isWhitespace(int) whitespace} and non-breaking spaces from the edges * of the label. * * @see #loadSafeLabel(PackageManager, float, int) + * + * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_TRIM} instead * @hide */ + @Deprecated @SystemApi - public static final int SAFE_LABEL_FLAG_TRIM = 0x1; + public static final int SAFE_LABEL_FLAG_TRIM = SAFE_STRING_FLAG_TRIM; /** * Force entire string into single line of text (no newlines). Cannot be set at the same time as * {@link #SAFE_LABEL_FLAG_FIRST_LINE}. * * @see #loadSafeLabel(PackageManager, float, int) + * + * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_SINGLE_LINE} instead * @hide */ + @Deprecated @SystemApi - public static final int SAFE_LABEL_FLAG_SINGLE_LINE = 0x2; + public static final int SAFE_LABEL_FLAG_SINGLE_LINE = SAFE_STRING_FLAG_SINGLE_LINE; /** * Return only first line of text (truncate at first newline). Cannot be set at the same time as * {@link #SAFE_LABEL_FLAG_SINGLE_LINE}. * * @see #loadSafeLabel(PackageManager, float, int) + * + * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_FIRST_LINE} instead * @hide */ + @Deprecated @SystemApi - public static final int SAFE_LABEL_FLAG_FIRST_LINE = 0x4; + public static final int SAFE_LABEL_FLAG_FIRST_LINE = SAFE_STRING_FLAG_FIRST_LINE; private static volatile boolean sForceSafeLabels = false; @@ -199,8 +192,8 @@ public class PackageItemInfo { */ public @NonNull CharSequence loadLabel(@NonNull PackageManager pm) { if (sForceSafeLabels) { - return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_LABEL_FLAG_TRIM - | SAFE_LABEL_FLAG_FIRST_LINE); + return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM + | SAFE_STRING_FLAG_FIRST_LINE); } else { return loadUnsafeLabel(pm); } @@ -223,16 +216,6 @@ public class PackageItemInfo { return packageName; } - private static boolean isNewline(int codePoint) { - int type = Character.getType(codePoint); - return type == Character.PARAGRAPH_SEPARATOR || type == Character.LINE_SEPARATOR - || codePoint == LINE_FEED_CODE_POINT; - } - - private static boolean isWhiteSpace(int codePoint) { - return Character.isWhitespace(codePoint) || codePoint == NBSP_CODE_POINT; - } - /** * @hide * @deprecated use loadSafeLabel(PackageManager, float, int) instead @@ -240,209 +223,24 @@ public class PackageItemInfo { @SystemApi @Deprecated public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm) { - return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_LABEL_FLAG_TRIM - | SAFE_LABEL_FLAG_FIRST_LINE); - } - - /** - * A special string manipulation class. Just records removals and executes the when onString() - * is called. - */ - private static class StringWithRemovedChars { - /** The original string */ - private final String mOriginal; - - /** - * One bit per char in string. If bit is set, character needs to be removed. If whole - * bit field is not initialized nothing needs to be removed. - */ - private BitSet mRemovedChars; - - StringWithRemovedChars(@NonNull String original) { - mOriginal = original; - } - - /** - * Mark all chars in a range {@code [firstRemoved - firstNonRemoved[} (not including - * firstNonRemoved) as removed. - */ - void removeRange(int firstRemoved, int firstNonRemoved) { - if (mRemovedChars == null) { - mRemovedChars = new BitSet(mOriginal.length()); - } - - mRemovedChars.set(firstRemoved, firstNonRemoved); - } - - /** - * Remove all characters before {@code firstNonRemoved}. - */ - void removeAllCharBefore(int firstNonRemoved) { - if (mRemovedChars == null) { - mRemovedChars = new BitSet(mOriginal.length()); - } - - mRemovedChars.set(0, firstNonRemoved); - } - - /** - * Remove all characters after and including {@code firstRemoved}. - */ - void removeAllCharAfter(int firstRemoved) { - if (mRemovedChars == null) { - mRemovedChars = new BitSet(mOriginal.length()); - } - - mRemovedChars.set(firstRemoved, mOriginal.length()); - } - - @Override - public String toString() { - // Common case, no chars removed - if (mRemovedChars == null) { - return mOriginal; - } - - StringBuilder sb = new StringBuilder(mOriginal.length()); - for (int i = 0; i < mOriginal.length(); i++) { - if (!mRemovedChars.get(i)) { - sb.append(mOriginal.charAt(i)); - } - } - - return sb.toString(); - } - - /** - * Return length or the original string - */ - int length() { - return mOriginal.length(); - } - - /** - * Return if a certain {@code offset} of the original string is removed - */ - boolean isRemoved(int offset) { - return mRemovedChars != null && mRemovedChars.get(offset); - } - - /** - * Return codePoint of original string at a certain {@code offset} - */ - int codePointAt(int offset) { - return mOriginal.codePointAt(offset); - } + return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM + | SAFE_STRING_FLAG_FIRST_LINE); } /** - * Load, clean up and truncate label before use. - * - * <p>This method is meant to remove common mistakes and nefarious formatting from strings that - * are used in sensitive parts of the UI. - * - * <p>This method first treats the string like HTML and then ... - * <ul> - * <li>Removes new lines or truncates at first new line - * <li>Trims the white-space off the end - * <li>Truncates the string to a given length - * </ul> - * ... if specified. - * - * @param ellipsizeDip Assuming maximum length of the string (in dip), assuming font size 42. - * This is roughly 50 characters for {@code ellipsizeDip == 1000}.<br /> - * Usually ellipsizing should be left to the view showing the string. If a - * string is used as an input to another string, it might be useful to - * control the length of the input string though. {@code 0} disables this - * feature. - * @return The safe label + * Calls {@link TextUtils#makeSafeForPresentation} for the label of this item. + * + * <p>For parameters see {@link TextUtils#makeSafeForPresentation}. + * * @hide - */ + */ @SystemApi public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm, - @FloatRange(from = 0) float ellipsizeDip, @SafeLabelFlags int flags) { - boolean onlyKeepFirstLine = ((flags & SAFE_LABEL_FLAG_FIRST_LINE) != 0); - boolean forceSingleLine = ((flags & SAFE_LABEL_FLAG_SINGLE_LINE) != 0); - boolean trim = ((flags & SAFE_LABEL_FLAG_TRIM) != 0); - + @FloatRange(from = 0) float ellipsizeDip, @TextUtils.SafeStringFlags int flags) { Preconditions.checkNotNull(pm); - Preconditions.checkArgument(ellipsizeDip >= 0); - Preconditions.checkFlagsArgument(flags, SAFE_LABEL_FLAG_TRIM | SAFE_LABEL_FLAG_SINGLE_LINE - | SAFE_LABEL_FLAG_FIRST_LINE); - Preconditions.checkArgument(!(onlyKeepFirstLine && forceSingleLine), - "Cannot set SAFE_LABEL_FLAG_SINGLE_LINE and SAFE_LABEL_FLAG_FIRST_LINE at the same " - + "time"); - - // loadLabel() always returns non-null - String label = loadUnsafeLabel(pm).toString(); - - // Treat string as HTML. This - // - converts HTML symbols: e.g. ß -> ß - // - applies some HTML tags: e.g. <br> -> \n - // - removes invalid characters such as \b - // - removes html styling, such as <b> - // - applies html formatting: e.g. a<p>b</p>c -> a\n\nb\n\nc - // - replaces some html tags by "object replacement" markers: <img> -> \ufffc - // - Removes leading white space - // - Removes all trailing white space beside a single space - // - Collapses double white space - StringWithRemovedChars labelStr = new StringWithRemovedChars( - Html.fromHtml(label).toString()); - - int firstNonWhiteSpace = -1; - int firstTrailingWhiteSpace = -1; - - // Remove new lines (if requested) and control characters. - int labelLength = labelStr.length(); - for (int offset = 0; offset < labelLength; ) { - int codePoint = labelStr.codePointAt(offset); - int type = Character.getType(codePoint); - int codePointLen = Character.charCount(codePoint); - boolean isNewline = isNewline(codePoint); - - if (offset > MAX_SAFE_LABEL_LENGTH || onlyKeepFirstLine && isNewline) { - labelStr.removeAllCharAfter(offset); - break; - } else if (forceSingleLine && isNewline) { - labelStr.removeRange(offset, offset + codePointLen); - } else if (type == Character.CONTROL && !isNewline) { - labelStr.removeRange(offset, offset + codePointLen); - } else if (trim && !isWhiteSpace(codePoint)) { - // This is only executed if the code point is not removed - if (firstNonWhiteSpace == -1) { - firstNonWhiteSpace = offset; - } - firstTrailingWhiteSpace = offset + codePointLen; - } - - offset += codePointLen; - } - - if (trim) { - // Remove leading and trailing white space - if (firstNonWhiteSpace == -1) { - // No non whitespace found, remove all - labelStr.removeAllCharAfter(0); - } else { - if (firstNonWhiteSpace > 0) { - labelStr.removeAllCharBefore(firstNonWhiteSpace); - } - if (firstTrailingWhiteSpace < labelLength) { - labelStr.removeAllCharAfter(firstTrailingWhiteSpace); - } - } - } - if (ellipsizeDip == 0) { - return labelStr.toString(); - } else { - // Truncate - final TextPaint paint = new TextPaint(); - paint.setTextSize(42); - - return TextUtils.ellipsize(labelStr.toString(), paint, ellipsizeDip, - TextUtils.TruncateAt.END); - } + return makeSafeForPresentation(loadUnsafeLabel(pm).toString(), MAX_SAFE_LABEL_LENGTH, + ellipsizeDip, flags); } /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 733fbe566b09..dfb8128e37ee 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -5664,7 +5664,7 @@ public abstract class PackageManager { * {@link Manifest.permission#MANAGE_USERS} to use this api.</p> * * @param packageNames The names of the packages to set the suspended status. - * @param suspended If set to {@code true} than the packages will be suspended, if set to + * @param suspended If set to {@code true}, the packages will be suspended, if set to * {@code false}, the packages will be unsuspended. * @param appExtras An optional {@link PersistableBundle} that the suspending app can provide * which will be shared with the apps being suspended. Ignored if @@ -5676,15 +5676,76 @@ public abstract class PackageManager { * suspended app. * * @return an array of package names for which the suspended status could not be set as - * requested in this method. + * requested in this method. Returns {@code null} if {@code packageNames} was {@code null}. + * + * @deprecated use {@link #setPackagesSuspended(String[], boolean, PersistableBundle, + * PersistableBundle, android.content.pm.SuspendDialogInfo)} instead. + * + * @hide + */ + @SystemApi + @Deprecated + @RequiresPermission(Manifest.permission.SUSPEND_APPS) + @Nullable + public String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended, + @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras, + @Nullable String dialogMessage) { + throw new UnsupportedOperationException("setPackagesSuspended not implemented"); + } + + /** + * Puts the given packages in a suspended state, where attempts at starting activities are + * denied. + * + * <p>The suspended application's notifications and all of its windows will be hidden, any + * of its started activities will be stopped and it won't be able to ring the device. + * It doesn't remove the data or the actual package file. + * + * <p>When the user tries to launch a suspended app, a system dialog alerting them that the app + * is suspended will be shown instead. + * The caller can optionally customize the dialog by passing a {@link SuspendDialogInfo} object + * to this api. This dialog will have a button that starts the + * {@link Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} intent if the suspending app declares an + * activity which handles this action. + * + * <p>The packages being suspended must already be installed. If a package is uninstalled, it + * will no longer be suspended. + * + * <p>Optionally, the suspending app can provide extra information in the form of + * {@link PersistableBundle} objects to be shared with the apps being suspended and the + * launcher to support customization that they might need to handle the suspended state. + * + * <p>The caller must hold {@link Manifest.permission#SUSPEND_APPS} to use this api. + * + * @param packageNames The names of the packages to set the suspended status. + * @param suspended If set to {@code true}, the packages will be suspended, if set to + * {@code false}, the packages will be unsuspended. + * @param appExtras An optional {@link PersistableBundle} that the suspending app can provide + * which will be shared with the apps being suspended. Ignored if + * {@code suspended} is false. + * @param launcherExtras An optional {@link PersistableBundle} that the suspending app can + * provide which will be shared with the launcher. Ignored if + * {@code suspended} is false. + * @param dialogInfo An optional {@link SuspendDialogInfo} object describing the dialog that + * should be shown to the user when they try to launch a suspended app. + * Ignored if {@code suspended} is false. + * + * @return an array of package names for which the suspended status could not be set as + * requested in this method. Returns {@code null} if {@code packageNames} was {@code null}. + * + * @see #isPackageSuspended + * @see SuspendDialogInfo + * @see SuspendDialogInfo.Builder + * @see Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.SUSPEND_APPS) - public String[] setPackagesSuspended(String[] packageNames, boolean suspended, + @Nullable + public String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended, @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras, - String dialogMessage) { + @Nullable SuspendDialogInfo dialogInfo) { throw new UnsupportedOperationException("setPackagesSuspended not implemented"); } diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 7b4c6fc64a69..4f58321da2f4 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -267,14 +267,15 @@ public abstract class PackageManagerInternal { public abstract String getSuspendingPackage(String suspendedPackage, int userId); /** - * Get the dialog message to be shown to the user when they try to launch a suspended - * application. + * Get the information describing the dialog to be shown to the user when they try to launch a + * suspended application. * * @param suspendedPackage The package that has been suspended. * @param userId The user for which to check. - * @return The dialog message to be shown to the user. + * @return A {@link SuspendDialogInfo} object describing the dialog to be shown. */ - public abstract String getSuspendedDialogMessage(String suspendedPackage, int userId); + @Nullable + public abstract SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId); /** * Do a straight uid lookup for the given package/application in the given user. diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java index 248d523a78ef..e21c33ad3bc1 100644 --- a/core/java/android/content/pm/PackageUserState.java +++ b/core/java/android/content/pm/PackageUserState.java @@ -33,6 +33,7 @@ import android.os.BaseBundle; import android.os.PersistableBundle; import android.util.ArraySet; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import java.util.Arrays; @@ -50,7 +51,7 @@ public class PackageUserState { public boolean hidden; // Is the app restricted by owner / admin public boolean suspended; public String suspendingPackage; - public String dialogMessage; // Message to show when a suspended package launch attempt is made + public SuspendDialogInfo dialogInfo; public PersistableBundle suspendedAppExtras; public PersistableBundle suspendedLauncherExtras; public boolean instantApp; @@ -79,6 +80,7 @@ public class PackageUserState { installReason = PackageManager.INSTALL_REASON_UNKNOWN; } + @VisibleForTesting public PackageUserState(PackageUserState o) { ceDataInode = o.ceDataInode; installed = o.installed; @@ -87,7 +89,7 @@ public class PackageUserState { hidden = o.hidden; suspended = o.suspended; suspendingPackage = o.suspendingPackage; - dialogMessage = o.dialogMessage; + dialogInfo = o.dialogInfo; suspendedAppExtras = o.suspendedAppExtras; suspendedLauncherExtras = o.suspendedLauncherExtras; instantApp = o.instantApp; @@ -217,7 +219,7 @@ public class PackageUserState { || !suspendingPackage.equals(oldState.suspendingPackage)) { return false; } - if (!Objects.equals(dialogMessage, oldState.dialogMessage)) { + if (!Objects.equals(dialogInfo, oldState.dialogInfo)) { return false; } if (!BaseBundle.kindofEquals(suspendedAppExtras, diff --git a/core/java/android/content/pm/SuspendDialogInfo.aidl b/core/java/android/content/pm/SuspendDialogInfo.aidl new file mode 100644 index 000000000000..5e711cfb01c2 --- /dev/null +++ b/core/java/android/content/pm/SuspendDialogInfo.aidl @@ -0,0 +1,18 @@ +/* + * 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.content.pm; + +parcelable SuspendDialogInfo; diff --git a/core/java/android/content/pm/SuspendDialogInfo.java b/core/java/android/content/pm/SuspendDialogInfo.java new file mode 100644 index 000000000000..c798c99fed90 --- /dev/null +++ b/core/java/android/content/pm/SuspendDialogInfo.java @@ -0,0 +1,379 @@ +/* + * 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.content.pm; + +import static android.content.res.ResourceId.ID_NULL; + +import android.annotation.DrawableRes; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.StringRes; +import android.annotation.SystemApi; +import android.content.res.ResourceId; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.util.Slog; + +import com.android.internal.util.Preconditions; +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.Locale; +import java.util.Objects; + +/** + * A container to describe the dialog to be shown when the user tries to launch a suspended + * application. + * The suspending app can customize the dialog's following attributes: + * <ul> + * <li>The dialog icon, by providing a resource id. + * <li>The title text, by providing a resource id. + * <li>The text of the dialog's body, by providing a resource id or a string. + * <li>The text on the neutral button which starts the + * {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS SHOW_SUSPENDED_APP_DETAILS} + * activity, by providing a resource id. + * </ul> + * System defaults are used whenever any of these are not provided, or any of the provided resource + * ids cannot be resolved at the time of displaying the dialog. + * + * @hide + * @see PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle, + * SuspendDialogInfo) + * @see Builder + */ +@SystemApi +public final class SuspendDialogInfo implements Parcelable { + private static final String TAG = SuspendDialogInfo.class.getSimpleName(); + private static final String XML_ATTR_ICON_RES_ID = "iconResId"; + private static final String XML_ATTR_TITLE_RES_ID = "titleResId"; + private static final String XML_ATTR_DIALOG_MESSAGE_RES_ID = "dialogMessageResId"; + private static final String XML_ATTR_DIALOG_MESSAGE = "dialogMessage"; + private static final String XML_ATTR_BUTTON_TEXT_RES_ID = "buttonTextResId"; + + private final int mIconResId; + private final int mTitleResId; + private final int mDialogMessageResId; + private final String mDialogMessage; + private final int mNeutralButtonTextResId; + + /** + * @return the resource id of the icon to be used with the dialog + * @hide + */ + @DrawableRes + public int getIconResId() { + return mIconResId; + } + + /** + * @return the resource id of the title to be used with the dialog + * @hide + */ + @StringRes + public int getTitleResId() { + return mTitleResId; + } + + /** + * @return the resource id of the text to be shown in the dialog's body + * @hide + */ + @StringRes + public int getDialogMessageResId() { + return mDialogMessageResId; + } + + /** + * @return the text to be shown in the dialog's body. Returns {@code null} if + * {@link #getDialogMessageResId()} returns a valid resource id. + * @hide + */ + @Nullable + public String getDialogMessage() { + return mDialogMessage; + } + + /** + * @return the text to be shown + * @hide + */ + @StringRes + public int getNeutralButtonTextResId() { + return mNeutralButtonTextResId; + } + + /** + * @hide + */ + public void saveToXml(XmlSerializer out) throws IOException { + if (mIconResId != ID_NULL) { + XmlUtils.writeIntAttribute(out, XML_ATTR_ICON_RES_ID, mIconResId); + } + if (mTitleResId != ID_NULL) { + XmlUtils.writeIntAttribute(out, XML_ATTR_TITLE_RES_ID, mTitleResId); + } + if (mDialogMessageResId != ID_NULL) { + XmlUtils.writeIntAttribute(out, XML_ATTR_DIALOG_MESSAGE_RES_ID, mDialogMessageResId); + } else { + XmlUtils.writeStringAttribute(out, XML_ATTR_DIALOG_MESSAGE, mDialogMessage); + } + if (mNeutralButtonTextResId != ID_NULL) { + XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_TEXT_RES_ID, mNeutralButtonTextResId); + } + } + + /** + * @hide + */ + public static SuspendDialogInfo restoreFromXml(XmlPullParser in) { + final SuspendDialogInfo.Builder dialogInfoBuilder = new SuspendDialogInfo.Builder(); + try { + final int iconId = XmlUtils.readIntAttribute(in, XML_ATTR_ICON_RES_ID, ID_NULL); + final int titleId = XmlUtils.readIntAttribute(in, XML_ATTR_TITLE_RES_ID, ID_NULL); + final int buttonTextId = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_TEXT_RES_ID, + ID_NULL); + final int dialogMessageResId = XmlUtils.readIntAttribute( + in, XML_ATTR_DIALOG_MESSAGE_RES_ID, ID_NULL); + final String dialogMessage = XmlUtils.readStringAttribute(in, XML_ATTR_DIALOG_MESSAGE); + + if (iconId != ID_NULL) { + dialogInfoBuilder.setIcon(iconId); + } + if (titleId != ID_NULL) { + dialogInfoBuilder.setTitle(titleId); + } + if (buttonTextId != ID_NULL) { + dialogInfoBuilder.setNeutralButtonText(buttonTextId); + } + if (dialogMessageResId != ID_NULL) { + dialogInfoBuilder.setMessage(dialogMessageResId); + } else if (dialogMessage != null) { + dialogInfoBuilder.setMessage(dialogMessage); + } + } catch (Exception e) { + Slog.e(TAG, "Exception while parsing from xml. Some fields may default", e); + } + return dialogInfoBuilder.build(); + } + + @Override + public int hashCode() { + int hashCode = mIconResId; + hashCode = 31 * hashCode + mTitleResId; + hashCode = 31 * hashCode + mNeutralButtonTextResId; + hashCode = 31 * hashCode + mDialogMessageResId; + hashCode = 31 * hashCode + Objects.hashCode(mDialogMessage); + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SuspendDialogInfo)) { + return false; + } + final SuspendDialogInfo otherDialogInfo = (SuspendDialogInfo) obj; + return mIconResId == otherDialogInfo.mIconResId + && mTitleResId == otherDialogInfo.mTitleResId + && mDialogMessageResId == otherDialogInfo.mDialogMessageResId + && mNeutralButtonTextResId == otherDialogInfo.mNeutralButtonTextResId + && Objects.equals(mDialogMessage, otherDialogInfo.mDialogMessage); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder("SuspendDialogInfo: {"); + if (mIconResId != ID_NULL) { + builder.append("mIconId = 0x"); + builder.append(Integer.toHexString(mIconResId)); + builder.append(" "); + } + if (mTitleResId != ID_NULL) { + builder.append("mTitleResId = 0x"); + builder.append(Integer.toHexString(mTitleResId)); + builder.append(" "); + } + if (mNeutralButtonTextResId != ID_NULL) { + builder.append("mNeutralButtonTextResId = 0x"); + builder.append(Integer.toHexString(mNeutralButtonTextResId)); + builder.append(" "); + } + if (mDialogMessageResId != ID_NULL) { + builder.append("mDialogMessageResId = 0x"); + builder.append(Integer.toHexString(mDialogMessageResId)); + builder.append(" "); + } else if (mDialogMessage != null) { + builder.append("mDialogMessage = \""); + builder.append(mDialogMessage); + builder.append("\" "); + } + builder.append("}"); + return builder.toString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int parcelableFlags) { + dest.writeInt(mIconResId); + dest.writeInt(mTitleResId); + dest.writeInt(mDialogMessageResId); + dest.writeString(mDialogMessage); + dest.writeInt(mNeutralButtonTextResId); + } + + private SuspendDialogInfo(Parcel source) { + mIconResId = source.readInt(); + mTitleResId = source.readInt(); + mDialogMessageResId = source.readInt(); + mDialogMessage = source.readString(); + mNeutralButtonTextResId = source.readInt(); + } + + SuspendDialogInfo(Builder b) { + mIconResId = b.mIconResId; + mTitleResId = b.mTitleResId; + mDialogMessageResId = b.mDialogMessageResId; + mDialogMessage = (mDialogMessageResId == ID_NULL) ? b.mDialogMessage : null; + mNeutralButtonTextResId = b.mNeutralButtonTextResId; + } + + public static final Creator<SuspendDialogInfo> CREATOR = new Creator<SuspendDialogInfo>() { + @Override + public SuspendDialogInfo createFromParcel(Parcel source) { + return new SuspendDialogInfo(source); + } + + @Override + public SuspendDialogInfo[] newArray(int size) { + return new SuspendDialogInfo[size]; + } + }; + + /** + * Builder to build a {@link SuspendDialogInfo} object. + */ + public static final class Builder { + private int mDialogMessageResId = ID_NULL; + private String mDialogMessage; + private int mTitleResId = ID_NULL; + private int mIconResId = ID_NULL; + private int mNeutralButtonTextResId = ID_NULL; + + /** + * Set the resource id of the icon to be used. If not provided, no icon will be shown. + * + * @param resId The resource id of the icon. + * @return this builder object. + */ + @NonNull + public Builder setIcon(@DrawableRes int resId) { + Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided"); + mIconResId = resId; + return this; + } + + /** + * Set the resource id of the title text to be displayed. If this is not provided, the + * system will use a default title. + * + * @param resId The resource id of the title. + * @return this builder object. + */ + @NonNull + public Builder setTitle(@StringRes int resId) { + Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided"); + mTitleResId = resId; + return this; + } + + /** + * Set the text to show in the body of the dialog. Ignored if a resource id is set via + * {@link #setMessage(int)}. + * <p> + * The system will use {@link String#format(Locale, String, Object...) String.format} to + * insert the suspended app name into the message, so an example format string could be + * {@code "The app %1$s is currently suspended"}. This is optional - if the string passed in + * {@code message} does not accept an argument, it will be used as is. + * + * @param message The dialog message. + * @return this builder object. + * @see #setMessage(int) + */ + @NonNull + public Builder setMessage(@NonNull String message) { + Preconditions.checkStringNotEmpty(message, "Message cannot be null or empty"); + mDialogMessage = message; + return this; + } + + /** + * Set the resource id of the dialog message to be shown. If no dialog message is provided + * via either this method or {@link #setMessage(String)}, the system will use a + * default message. + * <p> + * The system will use {@link android.content.res.Resources#getString(int, Object...) + * getString} to insert the suspended app name into the message, so an example format string + * could be {@code "The app %1$s is currently suspended"}. This is optional - if the string + * referred to by {@code resId} does not accept an argument, it will be used as is. + * + * @param resId The resource id of the dialog message. + * @return this builder object. + * @see #setMessage(String) + */ + @NonNull + public Builder setMessage(@StringRes int resId) { + Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided"); + mDialogMessageResId = resId; + return this; + } + + /** + * Set the resource id of text to be shown on the neutral button. Tapping this button starts + * the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity. If this is + * not provided, the system will use a default text. + * + * @param resId The resource id of the button text + * @return this builder object. + */ + @NonNull + public Builder setNeutralButtonText(@StringRes int resId) { + Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided"); + mNeutralButtonTextResId = resId; + return this; + } + + /** + * Build the final object based on given inputs. + * + * @return The {@link SuspendDialogInfo} object built using this builder. + */ + @NonNull + public SuspendDialogInfo build() { + return new SuspendDialogInfo(this); + } + } +} diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 09113e5d175d..01ef58e987d7 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -397,7 +397,7 @@ public final class DisplayManager { if (display == null) { // TODO: We cannot currently provide any override configurations for metrics on displays // other than the display the context is associated with. - final Context context = mContext.getDisplay().getDisplayId() == displayId + final Context context = mContext.getDisplayId() == displayId ? mContext : mContext.getApplicationContext(); display = mGlobal.getCompatibleDisplay(displayId, context.getResources()); diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 5f656207255a..df3aae2c901c 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -55,7 +55,7 @@ public class GraphicsEnvironment { * Set up GraphicsEnvironment */ public void setup(Context context, Bundle coreSettings) { - setupGpuLayers(context); + setupGpuLayers(context, coreSettings); setupAngle(context, coreSettings); chooseDriver(context); } @@ -81,27 +81,54 @@ public class GraphicsEnvironment { } /** + * Return the debug layer app's on-disk and in-APK lib directories + */ + private static String getDebugLayerAppPaths(Context context, String app) { + ApplicationInfo appInfo; + try { + appInfo = context.getPackageManager().getApplicationInfo( + app, PackageManager.MATCH_ALL); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Debug layer app '" + app + "' not installed"); + + return null; + } + + String abi = chooseAbi(appInfo); + + StringBuilder sb = new StringBuilder(); + sb.append(appInfo.nativeLibraryDir) + .append(File.pathSeparator); + sb.append(appInfo.sourceDir) + .append("!/lib/") + .append(abi); + String paths = sb.toString(); + + if (DEBUG) Log.v(TAG, "Debug layer app libs: " + paths); + + return paths; + } + + /** * Set up layer search paths for all apps * If debuggable, check for additional debug settings */ - private void setupGpuLayers(Context context) { + private void setupGpuLayers(Context context, Bundle coreSettings) { String layerPaths = ""; // Only enable additional debug functionality if the following conditions are met: - // 1. App is debuggable + // 1. App is debuggable or device is rooted // 2. ENABLE_GPU_DEBUG_LAYERS is true // 3. Package name is equal to GPU_DEBUG_APP - if (isDebuggable(context)) { + if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) { - int enable = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); + int enable = coreSettings.getInt(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); if (enable != 0) { - String gpuDebugApp = Settings.Global.getString(context.getContentResolver(), - Settings.Global.GPU_DEBUG_APP); + String gpuDebugApp = coreSettings.getString(Settings.Global.GPU_DEBUG_APP); String packageName = context.getPackageName(); @@ -115,8 +142,22 @@ public class GraphicsEnvironment { // the layers specified by the app. layerPaths = mDebugLayerPath + ":"; - String layers = Settings.Global.getString(context.getContentResolver(), - Settings.Global.GPU_DEBUG_LAYERS); + + // If there is a debug layer app specified, add its path. + String gpuDebugLayerApp = + coreSettings.getString(Settings.Global.GPU_DEBUG_LAYER_APP); + + if (gpuDebugLayerApp != null && !gpuDebugLayerApp.isEmpty()) { + Log.i(TAG, "GPU debug layer app: " + gpuDebugLayerApp); + String paths = getDebugLayerAppPaths(context, gpuDebugLayerApp); + if (paths != null) { + // Append the path so files placed in the app's base directory will + // override the external path + layerPaths += paths + ":"; + } + } + + String layers = coreSettings.getString(Settings.Global.GPU_DEBUG_LAYERS); Log.i(TAG, "Debug layer list: " + layers); if (layers != null && !layers.isEmpty()) { @@ -290,6 +331,7 @@ public class GraphicsEnvironment { return null; } + private static native int getCanLoadSystemLibraries(); private static native void setLayerPaths(ClassLoader classLoader, String layerPaths); private static native void setDebugLayers(String layers); private static native void setDriverPath(String path); diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 20ca19bc04aa..c9c42058bad0 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -388,10 +388,10 @@ interface INetworkManagementService /** * Setup a new physical network. - * @param permission null if no permissions required to access this network. PERMISSION_NETWORK - * or PERMISSION_SYSTEM to set respective permission. + * @param permission PERMISSION_NONE if no permissions required to access this network. + * PERMISSION_NETWORK or PERMISSION_SYSTEM to set respective permission. */ - void createPhysicalNetwork(int netId, String permission); + void createPhysicalNetwork(int netId, int permission); /** * Setup a new VPN. @@ -420,10 +420,10 @@ interface INetworkManagementService /** * Set permission for a network. - * @param permission null to clear permissions. PERMISSION_NETWORK or PERMISSION_SYSTEM to set - * permission. + * @param permission PERMISSION_NONE to clear permissions. + * PERMISSION_NETWORK or PERMISSION_SYSTEM to set permission. */ - void setNetworkPermission(int netId, String permission); + void setNetworkPermission(int netId, int permission); void setPermission(String permission, in int[] uids); void clearPermission(in int[] uids); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 8123744281f4..7ea20082e660 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -2363,7 +2363,6 @@ public class UserManager { */ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.CREATE_USERS}, conditional = true) - @SystemApi public @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) { try { return mService.getProfileIds(userId, enabledOnly); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index acb75778e08e..c6e457436025 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11631,6 +11631,12 @@ public final class Settings { public static final String GPU_DEBUG_LAYERS = "gpu_debug_layers"; /** + * Addition app for GPU layer discovery + * @hide + */ + public static final String GPU_DEBUG_LAYER_APP = "gpu_debug_layer_app"; + + /** * Control whether the process CPU usage meter should be shown. * * @deprecated This functionality is no longer available as of diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index c89617fefec5..0808cdd6aedb 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -23,6 +23,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; +import android.graphics.text.LineBreaker; import android.text.method.TextKeyListener; import android.text.style.AlignmentSpan; import android.text.style.LeadingMarginSpan; @@ -50,9 +51,9 @@ import java.util.Arrays; public abstract class Layout { /** @hide */ @IntDef(prefix = { "BREAK_STRATEGY_" }, value = { - NativeLineBreaker.BREAK_STRATEGY_SIMPLE, - NativeLineBreaker.BREAK_STRATEGY_HIGH_QUALITY, - NativeLineBreaker.BREAK_STRATEGY_BALANCED + LineBreaker.BREAK_STRATEGY_SIMPLE, + LineBreaker.BREAK_STRATEGY_HIGH_QUALITY, + LineBreaker.BREAK_STRATEGY_BALANCED }) @Retention(RetentionPolicy.SOURCE) public @interface BreakStrategy {} @@ -63,20 +64,19 @@ public abstract class Layout { * before it (which yields a more consistent user experience when editing), but layout may not * be the highest quality. */ - public static final int BREAK_STRATEGY_SIMPLE = NativeLineBreaker.BREAK_STRATEGY_SIMPLE; + public static final int BREAK_STRATEGY_SIMPLE = LineBreaker.BREAK_STRATEGY_SIMPLE; /** * Value for break strategy indicating high quality line breaking, including automatic * hyphenation and doing whole-paragraph optimization of line breaks. */ - public static final int BREAK_STRATEGY_HIGH_QUALITY = - NativeLineBreaker.BREAK_STRATEGY_HIGH_QUALITY; + public static final int BREAK_STRATEGY_HIGH_QUALITY = LineBreaker.BREAK_STRATEGY_HIGH_QUALITY; /** * Value for break strategy indicating balanced line breaking. The breaks are chosen to * make all lines as close to the same length as possible, including automatic hyphenation. */ - public static final int BREAK_STRATEGY_BALANCED = NativeLineBreaker.BREAK_STRATEGY_BALANCED; + public static final int BREAK_STRATEGY_BALANCED = LineBreaker.BREAK_STRATEGY_BALANCED; /** @hide */ @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = { @@ -94,32 +94,29 @@ public abstract class Layout { * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used * as suggestions for potential line breaks. */ - public static final int HYPHENATION_FREQUENCY_NONE = - NativeLineBreaker.HYPHENATION_FREQUENCY_NONE; + public static final int HYPHENATION_FREQUENCY_NONE = LineBreaker.HYPHENATION_FREQUENCY_NONE; /** * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which * is a conservative default. Useful for informal cases, such as short sentences or chat * messages. */ - public static final int HYPHENATION_FREQUENCY_NORMAL = - NativeLineBreaker.HYPHENATION_FREQUENCY_NORMAL; + public static final int HYPHENATION_FREQUENCY_NORMAL = LineBreaker.HYPHENATION_FREQUENCY_NORMAL; /** * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical * in typography. Useful for running text and where it's important to put the maximum amount of * text in a screen with limited space. */ - public static final int HYPHENATION_FREQUENCY_FULL = - NativeLineBreaker.HYPHENATION_FREQUENCY_FULL; + public static final int HYPHENATION_FREQUENCY_FULL = LineBreaker.HYPHENATION_FREQUENCY_FULL; private static final ParagraphStyle[] NO_PARA_SPANS = ArrayUtils.emptyArray(ParagraphStyle.class); /** @hide */ @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = { - NativeLineBreaker.JUSTIFICATION_MODE_NONE, - NativeLineBreaker.JUSTIFICATION_MODE_INTER_WORD + LineBreaker.JUSTIFICATION_MODE_NONE, + LineBreaker.JUSTIFICATION_MODE_INTER_WORD }) @Retention(RetentionPolicy.SOURCE) public @interface JustificationMode {} @@ -127,13 +124,13 @@ public abstract class Layout { /** * Value for justification mode indicating no justification. */ - public static final int JUSTIFICATION_MODE_NONE = NativeLineBreaker.JUSTIFICATION_MODE_NONE; + public static final int JUSTIFICATION_MODE_NONE = LineBreaker.JUSTIFICATION_MODE_NONE; /** * Value for justification mode indicating the text is justified by stretching word spacing. */ public static final int JUSTIFICATION_MODE_INTER_WORD = - NativeLineBreaker.JUSTIFICATION_MODE_INTER_WORD; + LineBreaker.JUSTIFICATION_MODE_INTER_WORD; /* * Line spacing multiplier for default line spacing. diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java index 9bf8cd20f441..0a2d65c9ebff 100644 --- a/core/java/android/text/MeasuredParagraph.java +++ b/core/java/android/text/MeasuredParagraph.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.text.MeasuredText; import android.text.AutoGrowArray.ByteArray; import android.text.AutoGrowArray.FloatArray; import android.text.AutoGrowArray.IntArray; @@ -121,7 +122,7 @@ public class MeasuredParagraph { private @Nullable IntArray mFontMetrics = new IntArray(4 * 4); // The native MeasuredParagraph. - private @Nullable NativeMeasuredParagraph mNativeMeasuredParagraph; + private @Nullable MeasuredText mMeasuredText; // Following two objects are for avoiding object allocation. private @NonNull TextPaint mCachedPaint = new TextPaint(); @@ -149,7 +150,7 @@ public class MeasuredParagraph { mWidths.clear(); mFontMetrics.clear(); mSpanEndCache.clear(); - mNativeMeasuredParagraph = null; + mMeasuredText = null; } /** @@ -245,8 +246,8 @@ public class MeasuredParagraph { * This is available only if the MeasuredParagraph is computed with buildForStaticLayout. * Returns null in other cases. */ - public NativeMeasuredParagraph getNativeMeasuredParagraph() { - return mNativeMeasuredParagraph; + public MeasuredText getMeasuredText() { + return mMeasuredText; } /** @@ -259,7 +260,7 @@ public class MeasuredParagraph { * @param end the exclusive end offset of the target region in the text */ public float getWidth(int start, int end) { - if (mNativeMeasuredParagraph == null) { + if (mMeasuredText == null) { // We have result in Java. final float[] widths = mWidths.getRawArray(); float r = 0.0f; @@ -269,7 +270,7 @@ public class MeasuredParagraph { return r; } else { // We have result in native. - return mNativeMeasuredParagraph.getWidth(start, end); + return mMeasuredText.getWidth(start, end); } } @@ -281,7 +282,7 @@ public class MeasuredParagraph { */ public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull Rect bounds) { - mNativeMeasuredParagraph.getBounds(mCopiedBuffer, start, end, bounds); + mMeasuredText.getBounds(start, end, bounds); } /** @@ -290,7 +291,7 @@ public class MeasuredParagraph { * This is available only if the MeasuredParagraph is computed with buildForStaticLayout. */ public float getCharWidthAt(@IntRange(from = 0) int offset) { - return mNativeMeasuredParagraph.getCharWidthAt(offset); + return mMeasuredText.getCharWidthAt(offset); } /** @@ -391,12 +392,13 @@ public class MeasuredParagraph { @Nullable MeasuredParagraph recycle) { final MeasuredParagraph mt = recycle == null ? obtain() : recycle; mt.resetAndAnalyzeBidi(text, start, end, textDir); - final NativeMeasuredParagraph.Builder builder = new NativeMeasuredParagraph.Builder(); + final MeasuredText.Builder builder = new MeasuredText.Builder(mt.mCopiedBuffer); + builder.setComputeHyphenation(computeHyphenation); + builder.setComputeLayout(computeLayout); if (mt.mTextLength == 0) { // Need to build empty native measured text for StaticLayout. // TODO: Stop creating empty measured text for empty lines. - mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation, - computeLayout); + mt.mMeasuredText = builder.build(); } else { if (mt.mSpanned == null) { // No style change by MetricsAffectingSpan. Just measure all text. @@ -417,8 +419,7 @@ public class MeasuredParagraph { mt.mSpanEndCache.append(spanEnd); } } - mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation, - computeLayout); + mt.mMeasuredText = builder.build(); } return mt; @@ -490,7 +491,7 @@ public class MeasuredParagraph { private void applyReplacementRun(@NonNull ReplacementSpan replacement, @IntRange(from = 0) int start, // inclusive, in copied buffer @IntRange(from = 0) int end, // exclusive, in copied buffer - @Nullable NativeMeasuredParagraph.Builder builder) { + @Nullable MeasuredText.Builder builder) { // Use original text. Shouldn't matter. // TODO: passing uninitizlied FontMetrics to developers. Do we need to keep this for // backward compatibility? or Should we initialize them for getFontMetricsInt? @@ -510,7 +511,7 @@ public class MeasuredParagraph { private void applyStyleRun(@IntRange(from = 0) int start, // inclusive, in copied buffer @IntRange(from = 0) int end, // exclusive, in copied buffer - @Nullable NativeMeasuredParagraph.Builder builder) { + @Nullable MeasuredText.Builder builder) { if (mLtrWithoutBidi) { // If the whole text is LTR direction, just apply whole region. @@ -552,7 +553,7 @@ public class MeasuredParagraph { @Nullable MetricAffectingSpan[] spans, @IntRange(from = 0) int start, // inclusive, in original text buffer @IntRange(from = 0) int end, // exclusive, in original text buffer - @Nullable NativeMeasuredParagraph.Builder builder) { + @Nullable MeasuredText.Builder builder) { mCachedPaint.set(paint); // XXX paint should not have a baseline shift, but... mCachedPaint.baselineShift = 0; @@ -658,6 +659,6 @@ public class MeasuredParagraph { * This only works if the MeasuredParagraph is computed with buildForStaticLayout. */ public @IntRange(from = 0) int getMemoryUsage() { - return mNativeMeasuredParagraph.getMemoryUsage(); + return mMeasuredText.getMemoryUsage(); } } diff --git a/core/java/android/text/NativeMeasuredParagraph.java b/core/java/android/text/NativeMeasuredParagraph.java deleted file mode 100644 index bfdccca2955b..000000000000 --- a/core/java/android/text/NativeMeasuredParagraph.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2010 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.text; - -import android.annotation.FloatRange; -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.graphics.Paint; -import android.graphics.Rect; - -import dalvik.annotation.optimization.CriticalNative; - -import libcore.util.NativeAllocationRegistry; - -/** - * A native implementation of measured paragraph. - * TODO: Consider to make this class public. - * @hide - */ -public class NativeMeasuredParagraph { - private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( - NativeMeasuredParagraph.class.getClassLoader(), nGetReleaseFunc(), 1024); - - private long mNativePtr; - private @NonNull char[] mChars; - - // Use builder instead. - private NativeMeasuredParagraph(long ptr, @NonNull char[] chars) { - mNativePtr = ptr; - mChars = chars; - } - - /** - * Returns a characters of this paragraph. - */ - public char[] getChars() { - return mChars; - } - - /** - * Returns a width of the given region - */ - public float getWidth(int start, int end) { - return nGetWidth(mNativePtr, start, end); - } - - /** - * Returns a memory usage of the native object. - */ - public int getMemoryUsage() { - return nGetMemoryUsage(mNativePtr); - } - - /** - * Fills the boundary box of the given region - */ - public void getBounds(char[] buf, int start, int end, Rect rect) { - nGetBounds(mNativePtr, buf, start, end, rect); - } - - /** - * Returns the width of the character at the given offset - */ - public float getCharWidthAt(int offset) { - return nGetCharWidthAt(mNativePtr, offset); - } - - /** - * Returns a native pointer of the underlying native object. - */ - public long getNativePtr() { - return mNativePtr; - } - - @CriticalNative - private static native float nGetWidth(/* Non Zero */ long nativePtr, - @IntRange(from = 0) int start, - @IntRange(from = 0) int end); - - @CriticalNative - private static native /* Non Zero */ long nGetReleaseFunc(); - - @CriticalNative - private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr); - - private static native void nGetBounds(long nativePtr, char[] buf, int start, int end, - Rect rect); - - @CriticalNative - private static native float nGetCharWidthAt(long nativePtr, int offset); - - /** - * A builder for the NativeMeasuredParagraph - */ - public static class Builder { - private final long mNativePtr; - - public Builder() { - mNativePtr = nInitBuilder(); - } - - /** - * Apply styles to given range - */ - public void addStyleRun(@NonNull Paint paint, int start, int end, boolean isRtl) { - nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl); - } - - /** - * Tells native that the given range is replaced with the object of given width. - */ - public void addReplacementRun(@NonNull Paint paint, int start, int end, float width) { - nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width); - } - - /** - * Build the NativeMeasuredParagraph - */ - public NativeMeasuredParagraph build(char[] text, boolean computeHyphenation, - boolean computeLayout) { - try { - long ptr = nBuildNativeMeasuredParagraph(mNativePtr, text, computeHyphenation, - computeLayout); - NativeMeasuredParagraph res = new NativeMeasuredParagraph(ptr, text); - sRegistry.registerNativeAllocation(res, ptr); - return res; - } finally { - nFreeBuilder(mNativePtr); - } - } - - private static native /* Non Zero */ long nInitBuilder(); - - /** - * Apply style to make native measured text. - * - * @param nativeBuilderPtr The native MeasuredParagraph builder pointer. - * @param paintPtr The native paint pointer to be applied. - * @param start The start offset in the copied buffer. - * @param end The end offset in the copied buffer. - * @param isRtl True if the text is RTL. - */ - private static native void nAddStyleRun(/* Non Zero */ long nativeBuilderPtr, - /* Non Zero */ long paintPtr, - @IntRange(from = 0) int start, - @IntRange(from = 0) int end, - boolean isRtl); - /** - * Apply ReplacementRun to make native measured text. - * - * @param nativeBuilderPtr The native MeasuredParagraph builder pointer. - * @param paintPtr The native paint pointer to be applied. - * @param start The start offset in the copied buffer. - * @param end The end offset in the copied buffer. - * @param width The width of the replacement. - */ - private static native void nAddReplacementRun(/* Non Zero */ long nativeBuilderPtr, - /* Non Zero */ long paintPtr, - @IntRange(from = 0) int start, - @IntRange(from = 0) int end, - @FloatRange(from = 0) float width); - - private static native long nBuildNativeMeasuredParagraph( - /* Non Zero */ long nativeBuilderPtr, - @NonNull char[] text, - boolean computeHyphenation, - boolean computeLayout); - - private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr); - } -} diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index d2f085369448..2cf0262a1d28 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.graphics.Paint; +import android.graphics.text.LineBreaker; import android.os.Build; import android.text.style.LeadingMarginSpan; import android.text.style.LeadingMarginSpan.LeadingMarginSpan2; @@ -55,7 +56,7 @@ public class StaticLayout extends Layout { * * - Create MeasuredParagraph by MeasuredParagraph.buildForStaticLayout which measures in * native. - * - Run NativeLineBreaker.computeLineBreaks() to obtain line breaks for the paragraph. + * - Run LineBreaker.computeLineBreaks() to obtain line breaks for the paragraph. * * After all paragraphs, call finish() to release expensive buffers. */ @@ -634,7 +635,7 @@ public class StaticLayout extends Layout { indents = null; } - final NativeLineBreaker lineBreaker = new NativeLineBreaker.Builder() + final LineBreaker lineBreaker = new LineBreaker.Builder() .setBreakStrategy(b.mBreakStrategy) .setHyphenationFrequency(b.mHyphenationFrequency) // TODO: Support more justification mode, e.g. letter spacing, stretching. @@ -642,8 +643,8 @@ public class StaticLayout extends Layout { .setIndents(indents) .build(); - NativeLineBreaker.ParagraphConstraints constraints = - new NativeLineBreaker.ParagraphConstraints(); + LineBreaker.ParagraphConstraints constraints = + new LineBreaker.ParagraphConstraints(); PrecomputedText.ParagraphInfo[] paragraphInfo = null; final Spanned spanned = (source instanceof Spanned) ? (Spanned) source : null; @@ -739,8 +740,8 @@ public class StaticLayout extends Layout { constraints.setIndent(firstWidth, firstWidthLineCount); constraints.setTabStops(variableTabStops, TAB_INCREMENT); - NativeLineBreaker.Result res = lineBreaker.computeLineBreaks( - measuredPara.getNativeMeasuredParagraph(), constraints, mLineCount); + LineBreaker.Result res = lineBreaker.computeLineBreaks( + measuredPara.getMeasuredText(), constraints, mLineCount); int breakCount = res.getLineCount(); if (lineBreakCapacity < breakCount) { lineBreakCapacity = breakCount; @@ -776,7 +777,7 @@ public class StaticLayout extends Layout { width += lineWidths[i]; } else { for (int j = (i == 0 ? 0 : breaks[i - 1]); j < breaks[i]; j++) { - width += measuredPara.getCharWidthAt(j - paraStart); + width += measuredPara.getCharWidthAt(j); } } hasTab |= hasTabs[i]; diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index e31e928bb917..195de07d8595 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -16,7 +16,10 @@ package android.text; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -42,6 +45,7 @@ import android.text.style.CharacterStyle; import android.text.style.EasyEditSpan; import android.text.style.ForegroundColorSpan; import android.text.style.LeadingMarginSpan; +import android.text.style.LineBackgroundSpan; import android.text.style.LocaleSpan; import android.text.style.ParagraphStyle; import android.text.style.QuoteSpan; @@ -69,7 +73,9 @@ import com.android.internal.R; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; import java.lang.reflect.Array; +import java.util.BitSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -87,6 +93,44 @@ public class TextUtils { private static final String ELLIPSIS_NORMAL = "\u2026"; // HORIZONTAL ELLIPSIS (…) private static final String ELLIPSIS_TWO_DOTS = "\u2025"; // TWO DOT LEADER (‥) + private static final int LINE_FEED_CODE_POINT = 10; + private static final int NBSP_CODE_POINT = 160; + + /** + * Flags for {@link #makeSafeForPresentation(String, int, float, int)} + * + * @hide + */ + @Retention(SOURCE) + @IntDef(flag = true, prefix = "CLEAN_STRING_FLAG_", + value = {SAFE_STRING_FLAG_TRIM, SAFE_STRING_FLAG_SINGLE_LINE, + SAFE_STRING_FLAG_FIRST_LINE}) + public @interface SafeStringFlags {} + + /** + * Remove {@link Character#isWhitespace(int) whitespace} and non-breaking spaces from the edges + * of the label. + * + * @see #makeSafeForPresentation(String, int, float, int) + */ + public static final int SAFE_STRING_FLAG_TRIM = 0x1; + + /** + * Force entire string into single line of text (no newlines). Cannot be set at the same time as + * {@link #SAFE_STRING_FLAG_FIRST_LINE}. + * + * @see #makeSafeForPresentation(String, int, float, int) + */ + public static final int SAFE_STRING_FLAG_SINGLE_LINE = 0x2; + + /** + * Return only first line of text (truncate at first newline). Cannot be set at the same time as + * {@link #SAFE_STRING_FLAG_SINGLE_LINE}. + * + * @see #makeSafeForPresentation(String, int, float, int) + */ + public static final int SAFE_STRING_FLAG_FIRST_LINE = 0x4; + /** {@hide} */ @NonNull public static String getEllipsisString(@NonNull TextUtils.TruncateAt method) { @@ -687,7 +731,9 @@ public class TextUtils { /** @hide */ public static final int ACCESSIBILITY_URL_SPAN = 26; /** @hide */ - public static final int LAST_SPAN = ACCESSIBILITY_URL_SPAN; + public static final int LINE_BACKGROUND_SPAN = 27; + /** @hide */ + public static final int LAST_SPAN = LINE_BACKGROUND_SPAN; /** * Flatten a CharSequence and whatever styles can be copied across processes @@ -878,6 +924,10 @@ public class TextUtils { readSpan(p, sp, new AccessibilityURLSpan(p)); break; + case LINE_BACKGROUND_SPAN: + readSpan(p, sp, new LineBackgroundSpan.Standard(p)); + break; + default: throw new RuntimeException("bogus span encoding " + kind); } @@ -2116,6 +2166,222 @@ public class TextUtils { return trimmed; } + private static boolean isNewline(int codePoint) { + int type = Character.getType(codePoint); + return type == Character.PARAGRAPH_SEPARATOR || type == Character.LINE_SEPARATOR + || codePoint == LINE_FEED_CODE_POINT; + } + + private static boolean isWhiteSpace(int codePoint) { + return Character.isWhitespace(codePoint) || codePoint == NBSP_CODE_POINT; + } + + /** + * Remove html, remove bad characters, and truncate string. + * + * <p>This method is meant to remove common mistakes and nefarious formatting from strings that + * were loaded from untrusted sources (such as other packages). + * + * <p>This method first {@link Html#fromHtml treats the string like HTML} and then ... + * <ul> + * <li>Removes new lines or truncates at first new line + * <li>Trims the white-space off the end + * <li>Truncates the string + * </ul> + * ... if specified. + * + * @param unclean The input string + * @param maxCharactersToConsider The maximum number of characters of {@code unclean} to + * consider from the input string. {@code 0} disables this + * feature. + * @param ellipsizeDip Assuming maximum length of the string (in dip), assuming font size 42. + * This is roughly 50 characters for {@code ellipsizeDip == 1000}.<br /> + * Usually ellipsizing should be left to the view showing the string. If a + * string is used as an input to another string, it might be useful to + * control the length of the input string though. {@code 0} disables this + * feature. + * @param flags Flags controlling cleaning behavior (Can be {@link #SAFE_STRING_FLAG_TRIM}, + * {@link #SAFE_STRING_FLAG_SINGLE_LINE}, + * and {@link #SAFE_STRING_FLAG_FIRST_LINE}) + * + * @return The cleaned string + */ + public static @NonNull CharSequence makeSafeForPresentation(@NonNull String unclean, + @IntRange(from = 0) int maxCharactersToConsider, + @FloatRange(from = 0) float ellipsizeDip, @SafeStringFlags int flags) { + boolean onlyKeepFirstLine = ((flags & SAFE_STRING_FLAG_FIRST_LINE) != 0); + boolean forceSingleLine = ((flags & SAFE_STRING_FLAG_SINGLE_LINE) != 0); + boolean trim = ((flags & SAFE_STRING_FLAG_TRIM) != 0); + + Preconditions.checkNotNull(unclean); + Preconditions.checkArgumentNonnegative(maxCharactersToConsider); + Preconditions.checkArgumentNonNegative(ellipsizeDip, "ellipsizeDip"); + Preconditions.checkFlagsArgument(flags, SAFE_STRING_FLAG_TRIM + | SAFE_STRING_FLAG_SINGLE_LINE | SAFE_STRING_FLAG_FIRST_LINE); + Preconditions.checkArgument(!(onlyKeepFirstLine && forceSingleLine), + "Cannot set SAFE_STRING_FLAG_SINGLE_LINE and SAFE_STRING_FLAG_FIRST_LINE at the" + + "same time"); + + String shortString; + if (maxCharactersToConsider > 0) { + shortString = unclean.substring(0, Math.min(unclean.length(), maxCharactersToConsider)); + } else { + shortString = unclean; + } + + // Treat string as HTML. This + // - converts HTML symbols: e.g. ß -> ß + // - applies some HTML tags: e.g. <br> -> \n + // - removes invalid characters such as \b + // - removes html styling, such as <b> + // - applies html formatting: e.g. a<p>b</p>c -> a\n\nb\n\nc + // - replaces some html tags by "object replacement" markers: <img> -> \ufffc + // - Removes leading white space + // - Removes all trailing white space beside a single space + // - Collapses double white space + StringWithRemovedChars gettingCleaned = new StringWithRemovedChars( + Html.fromHtml(shortString).toString()); + + int firstNonWhiteSpace = -1; + int firstTrailingWhiteSpace = -1; + + // Remove new lines (if requested) and control characters. + int uncleanLength = gettingCleaned.length(); + for (int offset = 0; offset < uncleanLength; ) { + int codePoint = gettingCleaned.codePointAt(offset); + int type = Character.getType(codePoint); + int codePointLen = Character.charCount(codePoint); + boolean isNewline = isNewline(codePoint); + + if (onlyKeepFirstLine && isNewline) { + gettingCleaned.removeAllCharAfter(offset); + break; + } else if (forceSingleLine && isNewline) { + gettingCleaned.removeRange(offset, offset + codePointLen); + } else if (type == Character.CONTROL && !isNewline) { + gettingCleaned.removeRange(offset, offset + codePointLen); + } else if (trim && !isWhiteSpace(codePoint)) { + // This is only executed if the code point is not removed + if (firstNonWhiteSpace == -1) { + firstNonWhiteSpace = offset; + } + firstTrailingWhiteSpace = offset + codePointLen; + } + + offset += codePointLen; + } + + if (trim) { + // Remove leading and trailing white space + if (firstNonWhiteSpace == -1) { + // No non whitespace found, remove all + gettingCleaned.removeAllCharAfter(0); + } else { + if (firstNonWhiteSpace > 0) { + gettingCleaned.removeAllCharBefore(firstNonWhiteSpace); + } + if (firstTrailingWhiteSpace < uncleanLength) { + gettingCleaned.removeAllCharAfter(firstTrailingWhiteSpace); + } + } + } + + if (ellipsizeDip == 0) { + return gettingCleaned.toString(); + } else { + // Truncate + final TextPaint paint = new TextPaint(); + paint.setTextSize(42); + + return TextUtils.ellipsize(gettingCleaned.toString(), paint, ellipsizeDip, + TextUtils.TruncateAt.END); + } + } + + /** + * A special string manipulation class. Just records removals and executes the when onString() + * is called. + */ + private static class StringWithRemovedChars { + /** The original string */ + private final String mOriginal; + + /** + * One bit per char in string. If bit is set, character needs to be removed. If whole + * bit field is not initialized nothing needs to be removed. + */ + private BitSet mRemovedChars; + + StringWithRemovedChars(@NonNull String original) { + mOriginal = original; + } + + /** + * Mark all chars in a range {@code [firstRemoved - firstNonRemoved[} (not including + * firstNonRemoved) as removed. + */ + void removeRange(int firstRemoved, int firstNonRemoved) { + if (mRemovedChars == null) { + mRemovedChars = new BitSet(mOriginal.length()); + } + + mRemovedChars.set(firstRemoved, firstNonRemoved); + } + + /** + * Remove all characters before {@code firstNonRemoved}. + */ + void removeAllCharBefore(int firstNonRemoved) { + if (mRemovedChars == null) { + mRemovedChars = new BitSet(mOriginal.length()); + } + + mRemovedChars.set(0, firstNonRemoved); + } + + /** + * Remove all characters after and including {@code firstRemoved}. + */ + void removeAllCharAfter(int firstRemoved) { + if (mRemovedChars == null) { + mRemovedChars = new BitSet(mOriginal.length()); + } + + mRemovedChars.set(firstRemoved, mOriginal.length()); + } + + @Override + public String toString() { + // Common case, no chars removed + if (mRemovedChars == null) { + return mOriginal; + } + + StringBuilder sb = new StringBuilder(mOriginal.length()); + for (int i = 0; i < mOriginal.length(); i++) { + if (!mRemovedChars.get(i)) { + sb.append(mOriginal.charAt(i)); + } + } + + return sb.toString(); + } + + /** + * Return length or the original string + */ + int length() { + return mOriginal.length(); + } + + /** + * Return codePoint of original string at a certain {@code offset} + */ + int codePointAt(int offset) { + return mOriginal.codePointAt(offset); + } + } + private static Object sLock = new Object(); private static char[] sTemp = null; diff --git a/core/java/android/text/style/LineBackgroundSpan.java b/core/java/android/text/style/LineBackgroundSpan.java index 9c7859fb11e4..5a55fd749150 100644 --- a/core/java/android/text/style/LineBackgroundSpan.java +++ b/core/java/android/text/style/LineBackgroundSpan.java @@ -16,15 +16,110 @@ package android.text.style; +import android.annotation.ColorInt; +import android.annotation.NonNull; +import android.annotation.Px; import android.graphics.Canvas; import android.graphics.Paint; +import android.os.Parcel; +import android.text.ParcelableSpan; +import android.text.TextUtils; -public interface LineBackgroundSpan -extends ParagraphStyle +/** + * Used to change the background of lines where the span is attached to. + */ +public interface LineBackgroundSpan extends ParagraphStyle { - public void drawBackground(Canvas c, Paint p, - int left, int right, - int top, int baseline, int bottom, - CharSequence text, int start, int end, - int lnum); + /** + * Draw the background on the canvas. + * + * @param canvas canvas on which the span should be rendered + * @param paint paint used to draw text, which should be left unchanged on exit + * @param left left position of the line relative to input canvas, in pixels + * @param right right position of the line relative to input canvas, in pixels + * @param top top position of the line relative to input canvas, in pixels + * @param baseline baseline of the text relative to input canvas, in pixels + * @param bottom bottom position of the line relative to input canvas, in pixels + * @param text current text + * @param start start character index of the line + * @param end end character index of the line + * @param lineNumber line number in the current text layout + */ + void drawBackground(@NonNull Canvas canvas, @NonNull Paint paint, + @Px int left, @Px int right, + @Px int top, @Px int baseline, @Px int bottom, + @NonNull CharSequence text, int start, int end, + int lineNumber); + /** + * Default implementation of the {@link LineBackgroundSpan}, which changes the background + * color of the lines to which the span is attached. + */ + class Standard implements LineBackgroundSpan, ParcelableSpan { + + private final int mColor; + + /** + * Constructor taking a color integer. + * + * @param color Color integer that defines the background color. + */ + public Standard(@ColorInt int color) { + mColor = color; + } + + /** + * Creates a {@link LineBackgroundSpan.Standard} from a parcel + */ + public Standard(@NonNull Parcel src) { + mColor = src.readInt(); + } + + @Override + public int getSpanTypeId() { + return getSpanTypeIdInternal(); + } + + /** @hide */ + @Override + public int getSpanTypeIdInternal() { + return TextUtils.LINE_BACKGROUND_SPAN; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + writeToParcelInternal(dest, flags); + } + + /** @hide */ + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { + dest.writeInt(mColor); + } + + /** + * @return the color of this span. + * @see Standard#Standard(int) + */ + @ColorInt + public final int getColor() { + return mColor; + } + + @Override + public void drawBackground(@NonNull Canvas canvas, @NonNull Paint paint, + @Px int left, @Px int right, + @Px int top, @Px int baseline, @Px int bottom, + @NonNull CharSequence text, int start, int end, + int lineNumber) { + final int originColor = paint.getColor(); + paint.setColor(mColor); + canvas.drawRect(left, right, top, bottom, paint); + paint.setColor(originColor); + } + } } diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java index 209451bcfe6a..cd2b6ce3dc67 100644 --- a/core/java/android/util/proto/ProtoInputStream.java +++ b/core/java/android/util/proto/ProtoInputStream.java @@ -737,8 +737,7 @@ public final class ProtoInputStream extends ProtoStream { fillBuffer(); if (mOffset + n <= mEnd) { // fast path read. String is well within the current buffer - String value = StringFactory.newStringFromBytes(mBuffer, mOffset, n, - StandardCharsets.UTF_8); + String value = new String(mBuffer, mOffset, n, StandardCharsets.UTF_8); incOffset(n); return value; } else if (n <= mBufferSize) { @@ -752,14 +751,13 @@ public final class ProtoInputStream extends ProtoStream { mDiscardedBytes += mOffset; mOffset = 0; - String value = StringFactory.newStringFromBytes(mBuffer, mOffset, n, - StandardCharsets.UTF_8); + String value = new String(mBuffer, mOffset, n, StandardCharsets.UTF_8); incOffset(n); return value; } // Otherwise, the string is too large to use the buffer. Create the string from a // separate byte array. - return StringFactory.newStringFromBytes(readRawBytes(n), 0, n, StandardCharsets.UTF_8); + return new String(readRawBytes(n), 0, n, StandardCharsets.UTF_8); } /** diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 29d3742ba632..cc58b8928f6e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -24192,7 +24192,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * </ul> * @return {@code true} if the method completes successfully, or * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to - * do a drag, and so no drag operation is in progress. + * do a drag because of another ongoing operation or some other reasons. */ public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags) { @@ -24235,51 +24235,51 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); } - if (mAttachInfo.mDragSurface != null) { - mAttachInfo.mDragSurface.release(); - } - mAttachInfo.mDragSurface = new Surface(); - mAttachInfo.mDragToken = null; final ViewRootImpl root = mAttachInfo.mViewRootImpl; final SurfaceSession session = new SurfaceSession(root.mSurface); - final SurfaceControl surface = new SurfaceControl.Builder(session) + final SurfaceControl surfaceControl = new SurfaceControl.Builder(session) .setName("drag surface") .setSize(shadowSize.x, shadowSize.y) .setFormat(PixelFormat.TRANSLUCENT) .build(); + final Surface surface = new Surface(); + surface.copyFrom(surfaceControl); + IBinder token = null; try { - mAttachInfo.mDragSurface.copyFrom(surface); - final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); + final Canvas canvas = surface.lockCanvas(null); try { canvas.drawColor(0, PorterDuff.Mode.CLEAR); shadowBuilder.onDrawShadow(canvas); } finally { - mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); + surface.unlockCanvasAndPost(canvas); } - // Cache the local state object for delivery with DragEvents - root.setLocalDragState(myLocalState); - // repurpose 'shadowSize' for the last touch point root.getLastTouchPoint(shadowSize); - mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag( - mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(), + token = mAttachInfo.mSession.performDrag( + mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(), shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data); if (ViewDebug.DEBUG_DRAG) { - Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken); + Log.d(VIEW_LOG_TAG, "performDrag returned " + token); } - - return mAttachInfo.mDragToken != null; + if (token != null) { + if (mAttachInfo.mDragSurface != null) { + mAttachInfo.mDragSurface.release(); + } + mAttachInfo.mDragSurface = surface; + mAttachInfo.mDragToken = token; + // Cache the local state object for delivery with DragEvents + root.setLocalDragState(myLocalState); + } + return token != null; } catch (Exception e) { Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); return false; } finally { - if (mAttachInfo.mDragToken == null) { - mAttachInfo.mDragSurface.destroy(); - mAttachInfo.mDragSurface = null; - root.setLocalDragState(null); + if (token == null) { + surface.destroy(); } session.kill(); } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 982737aedc74..c1e94d8ff97e 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1085,6 +1085,19 @@ public abstract class Window { * * <p>Refer to the individual flags for the permissions needed. * + * @param flags The flag bits to add. + * + * @hide + */ + public void addPrivateFlags(int flags) { + setPrivateFlags(flags, flags); + } + + /** + * Add system flag bits. + * + * <p>Refer to the individual flags for the permissions needed. + * * <p>Note: Only for updateable system components (aka. mainline modules) * * @param flags The flag bits to add. @@ -1092,8 +1105,8 @@ public abstract class Window { * @hide */ @SystemApi - public void addPrivateFlags(int flags) { - setPrivateFlags(flags, flags); + public void addSystemFlags(@WindowManager.LayoutParams.SystemFlags int flags) { + addPrivateFlags(flags); } /** diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 742df5e8a962..2d77cb4f3aca 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1670,7 +1670,7 @@ public interface WindowManager extends ViewManager { */ @SystemApi @RequiresPermission(permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS) - public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000; + public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000; /** * Indicates that this window is the rounded corners overlay present on some @@ -1708,6 +1708,18 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 0x00800000; /** + * An internal annotation for flags that can be specified to {@link #softInputMode}. + * + * @hide + */ + @SystemApi + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = { "SYSTEM_FLAG_" }, value = { + SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, + }) + public @interface SystemFlags {} + + /** * Control flags that are private to the platform. * @hide */ @@ -1781,8 +1793,8 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, name = "SUSTAINED_PERFORMANCE_MODE"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, - equals = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, + mask = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, + equals = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, name = "HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @ViewDebug.FlagToString( mask = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index ca2ccaf224db..e8e4b4aba0d4 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -48,6 +48,7 @@ import android.util.Pools.SimplePool; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.SparseArray; +import android.view.Display; import android.view.InputChannel; import android.view.InputEvent; import android.view.InputEventSender; @@ -265,7 +266,7 @@ public final class InputMethodManager { * @hide */ public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() { - getInstanceInternal(); + forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper()); } private static final Object sLock = new Object(); @@ -279,6 +280,17 @@ public final class InputMethodManager { static InputMethodManager sInstance; /** + * Global map between display to {@link InputMethodManager}. + * + * <p>Currently this map works like a so-called leaky singleton. Once an instance is registered + * for the associated display ID, that instance will never be garbage collected.</p> + * + * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p> + */ + @GuardedBy("sLock") + private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>(); + + /** * @hide Flag for IInputMethodManager.windowGainedFocus: a view in * the window has input focus. */ @@ -335,6 +347,8 @@ public final class InputMethodManager { // Our generic input connection if the current target does not have its own. final IInputContext mIInputContext; + private final int mDisplayId; + /** * True if this input method client is active, initially false. */ @@ -452,6 +466,29 @@ public final class InputMethodManager { return afm != null && afm.isAutofillUiShowing(); } + /** + * Checks the consistency between {@link InputMethodManager} state and {@link View} state. + * + * @param view {@link View} to be checked + * @return {@code true} if {@code view} is not {@code null} and there is a {@link Context} + * mismatch between {@link InputMethodManager} and {@code view} + */ + private boolean shouldDispatchToViewContext(@Nullable View view) { + if (view == null) { + return false; + } + final int viewDisplayId = view.getContext().getDisplayId(); + if (viewDisplayId != mDisplayId) { + Log.w(TAG, "b/117267690: Context mismatch found. view=" + view + " belongs to" + + " displayId=" + viewDisplayId + + " but InputMethodManager belongs to displayId=" + mDisplayId + + ". Use the right InputMethodManager instance to avoid performance overhead.", + new Throwable()); + return true; + } + return false; + } + private static boolean canStartInput(View servedView) { // We can start input ether the servedView has window focus // or the activity is showing autofill ui. @@ -733,33 +770,52 @@ public final class InputMethodManager { }); } - InputMethodManager(Looper looper) throws ServiceNotFoundException { + InputMethodManager(int displayId, Looper looper) throws ServiceNotFoundException { mService = getIInputMethodManager(); mMainLooper = looper; mH = new H(looper); + mDisplayId = displayId; mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this); } /** - * Retrieve the global {@link InputMethodManager} instance, creating it if it doesn't already - * exist. + * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist. * - * @return global {@link InputMethodManager} instance + * @param context {@link Context} for which IME APIs need to work + * @return {@link InputMethodManager} instance * @hide */ - public static InputMethodManager getInstanceInternal() { + @Nullable + public static InputMethodManager forContext(Context context) { + final int displayId = context.getDisplayId(); + // For better backward compatibility, we always use Looper.getMainLooper() for the default + // display case. + final Looper looper = displayId == Display.DEFAULT_DISPLAY + ? Looper.getMainLooper() : context.getMainLooper(); + return forContextInternal(displayId, looper); + } + + @Nullable + private static InputMethodManager forContextInternal(int displayId, Looper looper) { + final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY; synchronized (sLock) { - if (sInstance == null) { - try { - final InputMethodManager imm = new InputMethodManager(Looper.getMainLooper()); - imm.mService.addClient(imm.mClient, imm.mIInputContext); - sInstance = imm; - } catch (ServiceNotFoundException | RemoteException e) { - throw new IllegalStateException(e); - } + InputMethodManager instance = sInstanceMap.get(displayId); + if (instance != null) { + return instance; } - return sInstance; + try { + instance = new InputMethodManager(displayId, looper); + instance.mService.addClient(instance.mClient, instance.mIInputContext, displayId); + } catch (ServiceNotFoundException | RemoteException e) { + throw new IllegalStateException(e); + } + // For backward compatibility, store the instance also to sInstance for default display. + if (sInstance == null && isDefaultDisplay) { + sInstance = instance; + } + sInstanceMap.put(displayId, instance); + return instance; } } @@ -916,6 +972,11 @@ public final class InputMethodManager { * input method. */ public boolean isActive(View view) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + return view.getContext().getSystemService(InputMethodManager.class).isActive(view); + } + checkFocus(); synchronized (mH) { return (mServedView == view @@ -1006,6 +1067,13 @@ public final class InputMethodManager { } public void displayCompletions(View view, CompletionInfo[] completions) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class) + .displayCompletions(view, completions); + return; + } + checkFocus(); synchronized (mH) { if (mServedView != view && (mServedView == null @@ -1024,6 +1092,13 @@ public final class InputMethodManager { } public void updateExtractedText(View view, int token, ExtractedText text) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class) + .updateExtractedText(view, token, text); + return; + } + checkFocus(); synchronized (mH) { if (mServedView != view && (mServedView == null @@ -1065,6 +1140,12 @@ public final class InputMethodManager { * 0 or have the {@link #SHOW_IMPLICIT} bit set. */ public boolean showSoftInput(View view, int flags) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + return view.getContext().getSystemService(InputMethodManager.class) + .showSoftInput(view, flags); + } + return showSoftInput(view, flags, null); } @@ -1127,6 +1208,12 @@ public final class InputMethodManager { * {@link #RESULT_HIDDEN}. */ public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + return view.getContext().getSystemService(InputMethodManager.class) + .showSoftInput(view, flags, resultReceiver); + } + checkFocus(); synchronized (mH) { if (mServedView != view && (mServedView == null @@ -1290,6 +1377,12 @@ public final class InputMethodManager { * @param view The view whose text has changed. */ public void restartInput(View view) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class).restartInput(view); + return; + } + checkFocus(); synchronized (mH) { if (mServedView != view && (mServedView == null @@ -1714,6 +1807,13 @@ public final class InputMethodManager { */ public void updateSelection(View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class) + .updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd); + return; + } + checkFocus(); synchronized (mH) { if ((mServedView != view && (mServedView == null @@ -1751,6 +1851,12 @@ public final class InputMethodManager { * Notify the event when the user tapped or clicked the text view. */ public void viewClicked(View view) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class).viewClicked(view); + return; + } + final boolean focusChanged = mServedView != mNextServedView; checkFocus(); synchronized (mH) { @@ -1815,6 +1921,13 @@ public final class InputMethodManager { */ @Deprecated public void updateCursor(View view, int left, int top, int right, int bottom) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class) + .updateCursor(view, left, top, right, bottom); + return; + } + checkFocus(); synchronized (mH) { if ((mServedView != view && (mServedView == null @@ -1846,6 +1959,13 @@ public final class InputMethodManager { if (view == null || cursorAnchorInfo == null) { return; } + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class) + .updateCursorAnchorInfo(view, cursorAnchorInfo); + return; + } + checkFocus(); synchronized (mH) { if ((mServedView != view && @@ -1891,6 +2011,13 @@ public final class InputMethodManager { * @param data Any data to include with the command. */ public void sendAppPrivateCommand(View view, String action, Bundle data) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(view)) { + view.getContext().getSystemService(InputMethodManager.class) + .sendAppPrivateCommand(view, action, data); + return; + } + checkFocus(); synchronized (mH) { if ((mServedView != view && (mServedView == null @@ -2062,6 +2189,13 @@ public final class InputMethodManager { */ public void dispatchKeyEventFromInputMethod(@Nullable View targetView, @NonNull KeyEvent event) { + // Re-dispatch if there is a context mismatch. + if (shouldDispatchToViewContext(targetView)) { + targetView.getContext().getSystemService(InputMethodManager.class) + .dispatchKeyEventFromInputMethod(targetView, event); + return; + } + synchronized (mH) { ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null; if (viewRootImpl == null) { @@ -2551,6 +2685,7 @@ public final class InputMethodManager { sb.append(",windowFocus=" + view.hasWindowFocus()); sb.append(",autofillUiShowing=" + isAutofillUIShowing(view)); sb.append(",window=" + view.getWindowToken()); + sb.append(",displayId=" + view.getContext().getDisplayId()); sb.append(",temporaryDetach=" + view.isTemporarilyDetached()); return sb.toString(); } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 35ff6cc23499..8f17e96c144e 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -42,6 +42,7 @@ import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; +import android.graphics.drawable.RippleDrawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; @@ -152,6 +153,7 @@ public class RemoteViews implements Parcelable, Filter { private static final int SET_REMOTE_INPUTS_ACTION_TAG = 18; private static final int LAYOUT_PARAM_ACTION_TAG = 19; private static final int OVERRIDE_TEXT_COLORS_TAG = 20; + private static final int SET_RIPPLE_DRAWABLE_COLOR_TAG = 21; /** * Application that hosts the remote views. @@ -1122,6 +1124,53 @@ public class RemoteViews implements Parcelable, Filter { PorterDuff.Mode filterMode; } + /** + * Equivalent to calling + * {@link RippleDrawable#setColor(ColorStateList)}, + * on the {@link Drawable} of a given view. + * <p> + * The operation will be performed on the {@link Drawable} returned by the + * target {@link View#getBackground()}. + * <p> + */ + private class SetRippleDrawableColor extends Action { + + ColorStateList mColorStateList; + + SetRippleDrawableColor(int id, ColorStateList colorStateList) { + this.viewId = id; + this.mColorStateList = colorStateList; + } + + SetRippleDrawableColor(Parcel parcel) { + viewId = parcel.readInt(); + mColorStateList = parcel.readParcelable(null); + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(viewId); + dest.writeParcelable(mColorStateList, 0); + } + + @Override + public void apply(View root, ViewGroup rootParent, OnClickHandler handler) { + final View target = root.findViewById(viewId); + if (target == null) return; + + // Pick the correct drawable to modify for this view + Drawable targetDrawable = target.getBackground(); + + if (targetDrawable instanceof RippleDrawable) { + ((RippleDrawable) targetDrawable.mutate()).setColor(mColorStateList); + } + } + + @Override + public int getActionTag() { + return SET_RIPPLE_DRAWABLE_COLOR_TAG; + } + } + private final class ViewContentNavigation extends Action { final boolean mNext; @@ -2394,6 +2443,8 @@ public class RemoteViews implements Parcelable, Filter { return new LayoutParamAction(parcel); case OVERRIDE_TEXT_COLORS_TAG: return new OverrideTextColorsAction(parcel); + case SET_RIPPLE_DRAWABLE_COLOR_TAG: + return new SetRippleDrawableColor(parcel); default: throw new ActionException("Tag " + tag + " not found"); } @@ -2855,6 +2906,22 @@ public class RemoteViews implements Parcelable, Filter { /** * @hide + * Equivalent to calling + * {@link RippleDrawable#setColor(ColorStateList)} on the {@link Drawable} of a given view, + * assuming it's a {@link RippleDrawable}. + * <p> + * + * @param viewId The id of the view that contains the target + * {@link RippleDrawable} + * @param colorStateList Specify a color for a + * {@link ColorStateList} for this drawable. + */ + public void setRippleDrawableColor(int viewId, ColorStateList colorStateList) { + addAction(new SetRippleDrawableColor(viewId, colorStateList)); + } + + /** + * @hide * Equivalent to calling {@link android.widget.ProgressBar#setProgressTintList}. * * @param viewId The id of the view whose tint should change diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 10cf70215747..c256d57a6af6 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -137,7 +137,7 @@ public class Toast { String pkg = mContext.getOpPackageName(); TN tn = mTN; tn.mNextView = mNextView; - final int displayId = mContext.getDisplay().getDisplayId(); + final int displayId = mContext.getDisplayId(); try { service.enqueueToast(pkg, tn, mDuration, displayId); diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java index a8edfb6ec936..498de53b65e9 100644 --- a/core/java/com/android/internal/app/SuspendedAppActivity.java +++ b/core/java/com/android/internal/app/SuspendedAppActivity.java @@ -16,12 +16,17 @@ package com.android.internal.app; +import static android.content.res.ResourceId.ID_NULL; + import android.Manifest; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.SuspendDialogInfo; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; import android.util.Slog; @@ -31,16 +36,19 @@ import com.android.internal.R; public class SuspendedAppActivity extends AlertActivity implements DialogInterface.OnClickListener { - private static final String TAG = "SuspendedAppActivity"; - public static final String EXTRA_SUSPENDED_PACKAGE = - "SuspendedAppActivity.extra.SUSPENDED_PACKAGE"; + private static final String TAG = SuspendedAppActivity.class.getSimpleName(); + private static final String PACKAGE_NAME = "com.android.internal.app"; + + public static final String EXTRA_SUSPENDED_PACKAGE = PACKAGE_NAME + ".extra.SUSPENDED_PACKAGE"; public static final String EXTRA_SUSPENDING_PACKAGE = - "SuspendedAppActivity.extra.SUSPENDING_PACKAGE"; - public static final String EXTRA_DIALOG_MESSAGE = "SuspendedAppActivity.extra.DIALOG_MESSAGE"; + PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE"; + public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO"; private Intent mMoreDetailsIntent; private int mUserId; private PackageManager mPm; + private Resources mSuspendingAppResources; + private SuspendDialogInfo mSuppliedDialogInfo; private CharSequence getAppLabel(String packageName) { try { @@ -66,6 +74,65 @@ public class SuspendedAppActivity extends AlertActivity return null; } + private Drawable resolveIcon() { + final int iconId = (mSuppliedDialogInfo != null) ? mSuppliedDialogInfo.getIconResId() + : ID_NULL; + if (iconId != ID_NULL && mSuspendingAppResources != null) { + try { + return mSuspendingAppResources.getDrawable(iconId, null); + } catch (Resources.NotFoundException nfe) { + Slog.e(TAG, "Could not resolve drawable resource id " + iconId); + } + } + return null; + } + + private String resolveTitle() { + final int titleId = (mSuppliedDialogInfo != null) ? mSuppliedDialogInfo.getTitleResId() + : ID_NULL; + if (titleId != ID_NULL && mSuspendingAppResources != null) { + try { + return mSuspendingAppResources.getString(titleId); + } catch (Resources.NotFoundException nfe) { + Slog.e(TAG, "Could not resolve string resource id " + titleId); + } + } + return getString(R.string.app_suspended_title); + } + + private String resolveDialogMessage(String suspendingPkg, String suspendedPkg) { + final CharSequence suspendedAppLabel = getAppLabel(suspendedPkg); + if (mSuppliedDialogInfo != null) { + final int messageId = mSuppliedDialogInfo.getDialogMessageResId(); + final String message = mSuppliedDialogInfo.getDialogMessage(); + if (messageId != ID_NULL && mSuspendingAppResources != null) { + try { + return mSuspendingAppResources.getString(messageId, suspendedAppLabel); + } catch (Resources.NotFoundException nfe) { + Slog.e(TAG, "Could not resolve string resource id " + messageId); + } + } else if (message != null) { + return String.format(getResources().getConfiguration().getLocales().get(0), message, + suspendedAppLabel); + } + } + return getString(R.string.app_suspended_default_message, suspendedAppLabel, + getAppLabel(suspendingPkg)); + } + + private String resolveNeutralButtonText() { + final int buttonTextId = (mSuppliedDialogInfo != null) + ? mSuppliedDialogInfo.getNeutralButtonTextResId() : ID_NULL; + if (buttonTextId != ID_NULL && mSuspendingAppResources != null) { + try { + return mSuspendingAppResources.getString(buttonTextId); + } catch (Resources.NotFoundException nfe) { + Slog.e(TAG, "Could not resolve string resource id " + buttonTextId); + } + } + return getString(R.string.app_suspended_more_details); + } + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -79,26 +146,26 @@ public class SuspendedAppActivity extends AlertActivity finish(); return; } - final String suppliedMessage = intent.getStringExtra(EXTRA_DIALOG_MESSAGE); final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE); final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE); - final CharSequence suspendedAppLabel = getAppLabel(suspendedPackage); - final CharSequence dialogMessage; - if (suppliedMessage == null) { - dialogMessage = getString(R.string.app_suspended_default_message, suspendedAppLabel, - getAppLabel(suspendingPackage)); - } else { - dialogMessage = String.format(getResources().getConfiguration().getLocales().get(0), - suppliedMessage, suspendedAppLabel); + mSuppliedDialogInfo = intent.getParcelableExtra(EXTRA_DIALOG_INFO); + if (mSuppliedDialogInfo != null) { + try { + mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(suspendingPackage, + mUserId); + } catch (PackageManager.NameNotFoundException ne) { + Slog.e(TAG, "Could not find resources for " + suspendingPackage, ne); + } } final AlertController.AlertParams ap = mAlertParams; - ap.mTitle = getString(R.string.app_suspended_title); - ap.mMessage = dialogMessage; + ap.mIcon = resolveIcon(); + ap.mTitle = resolveTitle(); + ap.mMessage = resolveDialogMessage(suspendingPackage, suspendedPackage); ap.mPositiveButtonText = getString(android.R.string.ok); mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId); if (mMoreDetailsIntent != null) { - ap.mNeutralButtonText = getString(R.string.app_suspended_more_details); + ap.mNeutralButtonText = resolveNeutralButtonText(); } ap.mPositiveButtonListener = ap.mNeutralButtonListener = this; setupAlert(); @@ -116,11 +183,11 @@ public class SuspendedAppActivity extends AlertActivity } public static Intent createSuspendedAppInterceptIntent(String suspendedPackage, - String suspendingPackage, String dialogMessage, int userId) { + String suspendingPackage, SuspendDialogInfo dialogInfo, int userId) { return new Intent() .setClassName("android", SuspendedAppActivity.class.getName()) .putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage) - .putExtra(EXTRA_DIALOG_MESSAGE, dialogMessage) + .putExtra(EXTRA_DIALOG_INFO, dialogInfo) .putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage) .putExtra(Intent.EXTRA_USER_ID, userId) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 87515173e8de..3b7ce0a22b18 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -1387,7 +1387,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private int getOptionsPanelGravity() { try { return WindowManagerHolder.sWindowManager.getPreferredOptionsPanelGravity( - getContext().getDisplay().getDisplayId()); + getContext().getDisplayId()); } catch (RemoteException ex) { Log.e(TAG, "Couldn't getOptionsPanelGravity; using default", ex); return Gravity.CENTER | Gravity.BOTTOM; @@ -3642,7 +3642,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (!mIsWatching) { try { WindowManagerHolder.sWindowManager.watchRotation(this, - phoneWindow.getContext().getDisplay().getDisplayId()); + phoneWindow.getContext().getDisplayId()); mHandler = new Handler(); mIsWatching = true; } catch (RemoteException ex) { diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 5f1243f37542..dceacda5d4a3 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -31,7 +31,8 @@ import com.android.internal.view.IInputMethodClient; * applications. */ interface IInputMethodManager { - void addClient(in IInputMethodClient client, in IInputContext inputContext); + void addClient(in IInputMethodClient client, in IInputContext inputContext, + int untrustedDisplayId); // TODO: Use ParceledListSlice instead List<InputMethodInfo> getInputMethodList(); diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java index 101fd41f2925..ec8e8dacb9db 100644 --- a/core/java/com/android/internal/view/InputBindResult.java +++ b/core/java/com/android/internal/view/InputBindResult.java @@ -51,6 +51,9 @@ public final class InputBindResult implements Parcelable { ResultCode.ERROR_INVALID_USER, ResultCode.ERROR_NULL_EDITOR_INFO, ResultCode.ERROR_NOT_IME_TARGET_WINDOW, + ResultCode.ERROR_NO_EDITOR, + ResultCode.ERROR_DISPLAY_ID_MISMATCH, + ResultCode.ERROR_INVALID_DISPLAY_ID, }) public @interface ResultCode { /** @@ -139,13 +142,22 @@ public final class InputBindResult implements Parcelable { * The client should try to restart input when its {@link android.view.Window} is focused * again.</p> * - * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int) + * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int, int) */ int ERROR_NOT_IME_TARGET_WINDOW = 11; /** * Indicates that focused view in the current window is not an editor. */ int ERROR_NO_EDITOR = 12; + /** + * Indicates that there is a mismatch in display ID between IME client and focused Window. + */ + int ERROR_DISPLAY_ID_MISMATCH = 13; + /** + * Indicates that current IME client is no longer allowed to access to the associated + * display. + */ + int ERROR_INVALID_DISPLAY_ID = 14; } @ResultCode @@ -271,6 +283,10 @@ public final class InputBindResult implements Parcelable { return "ERROR_NULL_EDITOR_INFO"; case ResultCode.ERROR_NOT_IME_TARGET_WINDOW: return "ERROR_NOT_IME_TARGET_WINDOW"; + case ResultCode.ERROR_DISPLAY_ID_MISMATCH: + return "ERROR_DISPLAY_ID_MISMATCH"; + case ResultCode.ERROR_INVALID_DISPLAY_ID: + return "ERROR_INVALID_DISPLAY_ID"; default: return "Unknown(" + result + ")"; } @@ -316,4 +332,15 @@ public final class InputBindResult implements Parcelable { */ public static final InputBindResult INVALID_USER = error(ResultCode.ERROR_INVALID_USER); + /** + * Predefined error object for {@link ResultCode#ERROR_DISPLAY_ID_MISMATCH}. + */ + public static final InputBindResult DISPLAY_ID_MISMATCH = + error(ResultCode.ERROR_DISPLAY_ID_MISMATCH); + + /** + * Predefined error object for {@link ResultCode#ERROR_INVALID_DISPLAY_ID}. + */ + public static final InputBindResult INVALID_DISPLAY_ID = + error(ResultCode.ERROR_INVALID_DISPLAY_ID); } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index c2ca2fc35631..ed6445d92b13 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -84,8 +84,6 @@ cc_library_shared { "android_view_VelocityTracker.cpp", "android_text_AndroidCharacter.cpp", "android_text_Hyphenator.cpp", - "android_text_LineBreaker.cpp", - "android_text_MeasuredParagraph.cpp", "android_os_Debug.cpp", "android_os_GraphicsEnvironment.cpp", "android_os_HidlSupport.cpp", @@ -161,6 +159,8 @@ cc_library_shared { "android/graphics/pdf/PdfEditor.cpp", "android/graphics/pdf/PdfRenderer.cpp", "android/graphics/pdf/PdfUtils.cpp", + "android/graphics/text/LineBreaker.cpp", + "android/graphics/text/MeasuredText.cpp", "android_media_AudioRecord.cpp", "android_media_AudioSystem.cpp", "android_media_AudioTrack.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 6b55ed6d2289..c05bad2a4332 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -145,6 +145,8 @@ extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env); +extern int register_android_graphics_text_MeasuredText(JNIEnv* env); +extern int register_android_graphics_text_LineBreaker(JNIEnv *env); extern int register_android_view_DisplayEventReceiver(JNIEnv* env); extern int register_android_view_DisplayListCanvas(JNIEnv* env); extern int register_android_view_TextureLayer(JNIEnv* env); @@ -185,8 +187,6 @@ extern int register_android_net_LocalSocketImpl(JNIEnv* env); extern int register_android_net_NetworkUtils(JNIEnv* env); extern int register_android_text_AndroidCharacter(JNIEnv *env); extern int register_android_text_Hyphenator(JNIEnv *env); -extern int register_android_text_MeasuredParagraph(JNIEnv* env); -extern int register_android_text_LineBreaker(JNIEnv *env); extern int register_android_opengl_classes(JNIEnv *env); extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env); @@ -1336,8 +1336,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_content_res_ApkAssets), REG_JNI(register_android_text_AndroidCharacter), REG_JNI(register_android_text_Hyphenator), - REG_JNI(register_android_text_MeasuredParagraph), - REG_JNI(register_android_text_LineBreaker), REG_JNI(register_android_view_InputDevice), REG_JNI(register_android_view_KeyCharacterMap), REG_JNI(register_android_os_Process), @@ -1415,6 +1413,8 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), REG_JNI(register_android_graphics_pdf_PdfRenderer), + REG_JNI(register_android_graphics_text_MeasuredText), + REG_JNI(register_android_graphics_text_LineBreaker), REG_JNI(register_android_database_CursorWindow), REG_JNI(register_android_database_SQLiteConnection), diff --git a/core/jni/android_text_LineBreaker.cpp b/core/jni/android/graphics/text/LineBreaker.cpp index 543910727ffd..e1f2f2b8e069 100644 --- a/core/jni/android_text_LineBreaker.cpp +++ b/core/jni/android/graphics/text/LineBreaker.cpp @@ -168,8 +168,9 @@ static const JNINativeMethod gMethods[] = { {"nGetReleaseResultFunc", "()J", (void*)nGetReleaseResultFunc}, }; -int register_android_text_LineBreaker(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/text/NativeLineBreaker", gMethods, NELEM(gMethods)); +int register_android_graphics_text_LineBreaker(JNIEnv* env) { + return RegisterMethodsOrDie(env, "android/graphics/text/LineBreaker", gMethods, + NELEM(gMethods)); } } diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android/graphics/text/MeasuredText.cpp index 18f509c7ec60..0bfadb407a93 100644 --- a/core/jni/android_text_MeasuredParagraph.cpp +++ b/core/jni/android/graphics/text/MeasuredText.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "MeasuredParagraph" +#define LOG_TAG "MeasuredText" #include "GraphicsJNI.h" #include "unicode/locid.h" @@ -83,7 +83,7 @@ static void nAddReplacementRun(JNIEnv* /* unused */, jclass /* unused */, jlong } // Regular JNI -static jlong nBuildNativeMeasuredParagraph(JNIEnv* env, jclass /* unused */, jlong builderPtr, +static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr, jcharArray javaText, jboolean computeHyphenation, jboolean computeLayout) { ScopedCharArrayRO text(env, javaText); @@ -147,7 +147,7 @@ static const JNINativeMethod gMTBuilderMethods[] = { {"nInitBuilder", "()J", (void*) nInitBuilder}, {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun}, {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun}, - {"nBuildNativeMeasuredParagraph", "(J[CZZ)J", (void*) nBuildNativeMeasuredParagraph}, + {"nBuildMeasuredText", "(J[CZZ)J", (void*) nBuildMeasuredText}, {"nFreeBuilder", "(J)V", (void*) nFreeBuilder}, }; @@ -160,10 +160,10 @@ static const JNINativeMethod gMTMethods[] = { {"nGetCharWidthAt", "(JI)F", (void*) nGetCharWidthAt}, // Critical Native }; -int register_android_text_MeasuredParagraph(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/text/NativeMeasuredParagraph", +int register_android_graphics_text_MeasuredText(JNIEnv* env) { + return RegisterMethodsOrDie(env, "android/graphics/text/MeasuredText", gMTMethods, NELEM(gMTMethods)) - + RegisterMethodsOrDie(env, "android/text/NativeMeasuredParagraph$Builder", + + RegisterMethodsOrDie(env, "android/graphics/text/MeasuredText$Builder", gMTBuilderMethods, NELEM(gMTBuilderMethods)); } diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index b70485d9a0ea..92235ad494a7 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -23,6 +23,10 @@ namespace { +int getCanLoadSystemLibraries_native() { + return android::GraphicsEnv::getInstance().getCanLoadSystemLibraries(); +} + void setDriverPath(JNIEnv* env, jobject clazz, jstring path) { ScopedUtfChars pathChars(env, path); android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str()); @@ -51,6 +55,7 @@ void setDebugLayers_native(JNIEnv* env, jobject clazz, jstring layers) { } const JNINativeMethod g_methods[] = { + { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) }, { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) }, { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", reinterpret_cast<void*>(setAngleInfo_native) }, { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) }, diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index ecad6c027391..d023d22473c8 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -23,6 +23,7 @@ #include <atomic> #include <fcntl.h> #include <inttypes.h> +#include <mutex> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> @@ -69,6 +70,7 @@ static struct bindernative_offsets_t // Class state. jclass mClass; jmethodID mExecTransact; + jmethodID mGetInterfaceDescriptor; // Object state. jfieldID mObject; @@ -326,8 +328,32 @@ protected: env->DeleteGlobalRef(mObject); } - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) + const String16& getInterfaceDescriptor() const override + { + call_once(mPopulateDescriptor, [this] { + JNIEnv* env = javavm_to_jnienv(mVM); + + ALOGV("getInterfaceDescriptor() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); + + jstring descriptor = (jstring)env->CallObjectMethod(mObject, gBinderOffsets.mGetInterfaceDescriptor); + + if (descriptor == nullptr) { + return; + } + + static_assert(sizeof(jchar) == sizeof(char16_t), ""); + const jchar* descriptorChars = env->GetStringChars(descriptor, nullptr); + const char16_t* rawDescriptor = reinterpret_cast<const char16_t*>(descriptorChars); + jsize rawDescriptorLen = env->GetStringLength(descriptor); + mDescriptor = String16(rawDescriptor, rawDescriptorLen); + env->ReleaseStringChars(descriptor, descriptorChars); + }); + + return mDescriptor; + } + + status_t onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override { JNIEnv* env = javavm_to_jnienv(mVM); @@ -376,7 +402,7 @@ protected: return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; } - virtual status_t dump(int fd, const Vector<String16>& args) + status_t dump(int fd, const Vector<String16>& args) override { return 0; } @@ -384,6 +410,9 @@ protected: private: JavaVM* const mVM; jobject const mObject; // GlobalRef to Java Binder + + mutable std::once_flag mPopulateDescriptor; + mutable String16 mDescriptor; }; // ---------------------------------------------------------------------------- @@ -926,6 +955,8 @@ static int int_register_android_os_Binder(JNIEnv* env) gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z"); + gBinderOffsets.mGetInterfaceDescriptor = GetMethodIDOrDie(env, clazz, "getInterfaceDescriptor", + "()Ljava/lang/String;"); gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J"); return RegisterMethodsOrDie( diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index a02602ee5d99..47dbc0716c94 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -397,9 +397,10 @@ message GlobalSettingsProto { // Ordered GPU debug layer list // i.e. <layer1>:<layer2>:...:<layerN> optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; - // App will load ANGLE instead of native GLES drivers. optional SettingProto angle_enabled_app = 3; + // App that can provide layer libraries. + optional SettingProto debug_layer_app = 4; } optional Gpu gpu = 59; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index d24b0026f939..1ae5f03a2f04 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2770,7 +2770,7 @@ android:protectionLevel="signature" /> <!-- @SystemApi Allows an application to use - {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} + {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} to hide non-system-overlay windows. <p>Not for use by third-party applications. @hide diff --git a/core/res/res/layout/notification_material_media_action.xml b/core/res/res/layout/notification_material_media_action.xml index 900ca2dd7667..dd79a0bb1817 100644 --- a/core/res/res/layout/notification_material_media_action.xml +++ b/core/res/res/layout/notification_material_media_action.xml @@ -18,7 +18,6 @@ <ImageButton xmlns:android="http://schemas.android.com/apk/res/android" style="@android:style/Widget.Material.Button.Borderless.Small" - android:id="@+id/action0" android:layout_width="@dimen/media_notification_action_button_size" android:layout_height="@dimen/media_notification_action_button_size" android:paddingBottom="8dp" @@ -28,4 +27,5 @@ android:layout_marginEnd="2dp" android:gravity="center" android:background="@drawable/notification_material_media_action_background" + android:visibility="gone" /> diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml index b4e26483a2ad..5cb93eb9319a 100644 --- a/core/res/res/layout/notification_template_material_big_media.xml +++ b/core/res/res/layout/notification_template_material_big_media.xml @@ -59,7 +59,26 @@ android:orientation="horizontal" android:layoutDirection="ltr" style="@style/NotificationMediaActionContainer" > - <!-- media buttons will be added here --> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action0" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action1" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action2" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action3" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action4" + /> </LinearLayout> </LinearLayout> </com.android.internal.widget.MediaNotificationView> diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml index 3a0912bd2a90..01b0866f428c 100644 --- a/core/res/res/layout/notification_template_material_media.xml +++ b/core/res/res/layout/notification_template_material_media.xml @@ -65,7 +65,18 @@ android:layoutDirection="ltr" android:orientation="horizontal" > - <!-- media buttons will be added here --> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action0" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action1" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action2" + /> </LinearLayout> </LinearLayout> </FrameLayout> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index aeeba59b694b..7b01e8a9e15a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -697,6 +697,10 @@ <!-- Wifi driver supports IEEE80211AC for softap --> <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool> + <!-- Indicates that local-only hotspot should be brought up at 5GHz. This option is + for automotive builds only (the one that have PackageManager#FEATURE_AUTOMOTIVE) --> + <bool translatable="false" name="config_wifi_local_only_hotspot_5ghz">false</bool> + <!-- Flag indicating whether we should enable the automatic brightness. Software implementation will be used if config_hardware_auto_brightness_available is not set --> <bool name="config_automatic_brightness_available">false</bool> @@ -3367,22 +3371,22 @@ <bool name="config_sendPackageName">false</bool> <!-- Name for the set of keys associating package names --> - <string name="config_help_package_name_key" translatable="false"></string> + <string name="config_helpPackageNameKey" translatable="false"></string> <!-- Name for the set of values of package names --> - <string name="config_help_package_name_value" translatable="false"></string> + <string name="config_helpPackageNameValue" translatable="false"></string> <!-- Intent key for the package name keys --> - <string name="config_help_intent_extra_key" translatable="false"></string> + <string name="config_helpIntentExtraKey" translatable="false"></string> <!-- Intent key for package name values --> - <string name="config_help_intent_name_key" translatable="false"></string> + <string name="config_helpIntentNameKey" translatable="false"></string> <!-- Intent key for the package name keys --> - <string name="config_feedback_intent_extra_key" translatable="false"></string> + <string name="config_feedbackIntentExtraKey" translatable="false"></string> <!-- Intent key for package name values --> - <string name="config_feedback_intent_name_key" translatable="false"></string> + <string name="config_feedbackIntentNameKey" translatable="false"></string> <!-- The apps that need to be hidden when they are disabled --> <string-array name="config_hideWhenDisabled_packageNames"></string-array> @@ -3487,7 +3491,7 @@ <string name="config_headlineFontFamilyMedium">@string/font_family_button_material</string> <!-- Size of icon shown beside a preference locked by admin --> - <dimen name="config_restricted_icon_size">@dimen/restricted_icon_size_material</dimen> + <dimen name="config_restrictedIconSize">@dimen/restricted_icon_size_material</dimen> <string translatable="false" name="config_batterySaverDeviceSpecificConfig"></string> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 2e42e4ac27f3..95517186fe9e 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2930,17 +2930,17 @@ <public-group type="string" first-id="0x0104001b"> <!-- @hide @SystemApi --> - <public name="config_help_package_name_key" /> + <public name="config_helpPackageNameKey" /> <!-- @hide @SystemApi --> - <public name="config_help_package_name_value" /> + <public name="config_helpPackageNameValue" /> <!-- @hide @SystemApi --> - <public name="config_help_intent_extra_key" /> + <public name="config_helpIntentExtraKey" /> <!-- @hide @SystemApi --> - <public name="config_help_intent_name_key" /> + <public name="config_helpIntentNameKey" /> <!-- @hide @SystemApi --> - <public name="config_feedback_intent_extra_key" /> + <public name="config_feedbackIntentExtraKey" /> <!-- @hide @SystemApi --> - <public name="config_feedback_intent_name_key" /> + <public name="config_feedbackIntentNameKey" /> </public-group> <public-group type="bool" first-id="0x01110000"> @@ -2950,7 +2950,7 @@ <public-group type="dimen" first-id="0x01050007"> <!-- @hide @SystemApi --> - <public name="config_restricted_icon_size" /> + <public name="config_restrictedIconSize" /> </public-group> <!-- =============================================================== diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6f28b2c36e16..97bfcc14fc42 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -186,6 +186,8 @@ <java-symbol type="id" name="action0" /> <java-symbol type="id" name="action1" /> <java-symbol type="id" name="action2" /> + <java-symbol type="id" name="action3" /> + <java-symbol type="id" name="action4" /> <java-symbol type="id" name="big_picture" /> <java-symbol type="id" name="big_text" /> <java-symbol type="id" name="chronometer" /> @@ -1873,6 +1875,7 @@ <java-symbol type="bool" name="config_wifi_background_scan_support" /> <java-symbol type="bool" name="config_wifi_dual_band_support" /> <java-symbol type="bool" name="config_wifi_convert_apband_5ghz_to_any" /> + <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" /> <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" /> <java-symbol type="bool" name="config_wimaxEnabled" /> <java-symbol type="bool" name="show_ongoing_ime_switcher" /> @@ -3270,12 +3273,12 @@ <java-symbol type="integer" name="default_data_warning_level_mb" /> <java-symbol type="bool" name="config_useVideoPauseWorkaround" /> <java-symbol type="bool" name="config_sendPackageName" /> - <java-symbol type="string" name="config_help_package_name_key" /> - <java-symbol type="string" name="config_help_package_name_value" /> - <java-symbol type="string" name="config_help_intent_extra_key" /> - <java-symbol type="string" name="config_help_intent_name_key" /> - <java-symbol type="string" name="config_feedback_intent_extra_key" /> - <java-symbol type="string" name="config_feedback_intent_name_key" /> + <java-symbol type="string" name="config_helpPackageNameKey" /> + <java-symbol type="string" name="config_helpPackageNameValue" /> + <java-symbol type="string" name="config_helpIntentExtraKey" /> + <java-symbol type="string" name="config_helpIntentNameKey" /> + <java-symbol type="string" name="config_feedbackIntentExtraKey" /> + <java-symbol type="string" name="config_feedbackIntentNameKey" /> <java-symbol type="array" name="config_hideWhenDisabled_packageNames" /> diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk index 307e2e8671b2..041fb7eeb6b3 100644 --- a/core/tests/coretests/Android.mk +++ b/core/tests/coretests/Android.mk @@ -47,7 +47,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ LOCAL_JAVA_LIBRARIES := \ android.test.runner \ - conscrypt \ telephony-common \ org.apache.http.legacy \ android.test.base \ diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java new file mode 100644 index 000000000000..c8a3098690be --- /dev/null +++ b/core/tests/coretests/src/android/content/ContextTest.java @@ -0,0 +1,60 @@ +/* + * 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.content; + +import static org.junit.Assert.assertEquals; + +import android.app.ActivityThread; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.WindowManager; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ContextTest { + @Test + public void testDisplayIdForSystemContext() { + final Context systemContext = + ActivityThread.currentActivityThread().getSystemContext(); + + assertEquals(systemContext.getDisplay().getDisplayId(), systemContext.getDisplayId()); + } + + @Test + public void testDisplayIdForTestContext() { + final Context testContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals(testContext.getDisplay().getDisplayId(), testContext.getDisplayId()); + } + + @Test + public void testDisplayIdForDefaultDisplayContext() { + final Context testContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + final WindowManager wm = testContext.getSystemService(WindowManager.class); + final Context defaultDisplayContext = + testContext.createDisplayContext(wm.getDefaultDisplay()); + + assertEquals(defaultDisplayContext.getDisplay().getDisplayId(), + defaultDisplayContext.getDisplayId()); + } +} diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 60abd9468179..632c37fd54d2 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -450,6 +450,7 @@ public class SettingsBackupTest { Settings.Global.GPU_DEBUG_APP, Settings.Global.GPU_DEBUG_LAYERS, Settings.Global.ANGLE_ENABLED_APP, + Settings.Global.GPU_DEBUG_LAYER_APP, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS, diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java index f3d6013b8ee3..3d15eb9577b5 100644 --- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java +++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java @@ -73,7 +73,7 @@ public class MeasuredParagraphTest { assertEquals(0, mt.getWidths().size()); assertEquals(0, mt.getSpanEndCache().size()); assertEquals(0, mt.getFontMetrics().size()); - assertNull(mt.getNativeMeasuredParagraph()); + assertNull(mt.getMeasuredText()); // Recycle it MeasuredParagraph mt2 = MeasuredParagraph.buildForBidi("_VVV_", 1, 4, RTL, mt); @@ -85,7 +85,7 @@ public class MeasuredParagraphTest { assertEquals(0, mt2.getWidths().size()); assertEquals(0, mt2.getSpanEndCache().size()); assertEquals(0, mt2.getFontMetrics().size()); - assertNull(mt.getNativeMeasuredParagraph()); + assertNull(mt.getMeasuredText()); mt2.recycle(); } @@ -107,7 +107,7 @@ public class MeasuredParagraphTest { assertEquals(10, mt.getWidths().get(2), 0); assertEquals(0, mt.getSpanEndCache().size()); assertEquals(0, mt.getFontMetrics().size()); - assertNull(mt.getNativeMeasuredParagraph()); + assertNull(mt.getMeasuredText()); // Recycle it MeasuredParagraph mt2 = @@ -124,7 +124,7 @@ public class MeasuredParagraphTest { assertEquals(5, mt2.getWidths().get(2), 0); assertEquals(0, mt2.getSpanEndCache().size()); assertEquals(0, mt2.getFontMetrics().size()); - assertNull(mt.getNativeMeasuredParagraph()); + assertNull(mt.getMeasuredText()); mt2.recycle(); } @@ -144,7 +144,7 @@ public class MeasuredParagraphTest { assertEquals(1, mt.getSpanEndCache().size()); assertEquals(3, mt.getSpanEndCache().get(0)); assertNotEquals(0, mt.getFontMetrics().size()); - assertNotNull(mt.getNativeMeasuredParagraph()); + assertNotNull(mt.getMeasuredText()); // Recycle it MeasuredParagraph mt2 = @@ -159,7 +159,7 @@ public class MeasuredParagraphTest { assertEquals(1, mt2.getSpanEndCache().size()); assertEquals(4, mt2.getSpanEndCache().get(0)); assertNotEquals(0, mt2.getFontMetrics().size()); - assertNotNull(mt.getNativeMeasuredParagraph()); + assertNotNull(mt.getMeasuredText()); mt2.recycle(); } diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index 0885a05c74f3..ea0a109c3a04 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -549,7 +549,7 @@ public abstract class BaseCanvas { contextStart - paraStart, contextEnd - contextStart, x, y, isRtl, paint.getNativeInstance(), - mp.getNativeMeasuredParagraph().getNativePtr()); + mp.getMeasuredText().getNativePtr()); return; } } diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index fb30ca2d4090..4de7ca708eb6 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -520,7 +520,7 @@ public class BaseRecordingCanvas extends Canvas { contextStart - paraStart, contextEnd - contextStart, x, y, isRtl, paint.getNativeInstance(), - mp.getNativeMeasuredParagraph().getNativePtr()); + mp.getMeasuredText().getNativePtr()); return; } } diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index b65fb9cd24ec..2e1d81a294e9 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -472,8 +472,8 @@ public abstract class ColorSpace { * <tr> * <td>Electro-optical transfer function (EOTF)</td> * <td colspan="4">\(\begin{equation} - * C_{linear} = \begin{cases}\frac{C_{DisplayP3}}{12.92} & C_{sRGB} \lt 0.039 \\\ - * \left( \frac{C_{DisplayP3} + 0.055}{1.055} \right) ^{2.4} & C_{sRGB} \ge 0.039 \end{cases} + * C_{linear} = \begin{cases}\frac{C_{DisplayP3}}{12.92} & C_{sRGB} \lt 0.04045 \\\ + * \left( \frac{C_{DisplayP3} + 0.055}{1.055} \right) ^{2.4} & C_{sRGB} \ge 0.04045 \end{cases} * \end{equation}\) * </td> * </tr> @@ -1484,7 +1484,7 @@ public abstract class ColorSpace { "Display P3", new float[] { 0.680f, 0.320f, 0.265f, 0.690f, 0.150f, 0.060f }, ILLUMINANT_D65, - new Rgb.TransferParameters(1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.039, 2.4), + new Rgb.TransferParameters(1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4), Named.DISPLAY_P3.ordinal() ); sNamedColorSpaces[Named.NTSC_1953.ordinal()] = new ColorSpace.Rgb( diff --git a/core/java/android/text/NativeLineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java index 94e10e89acbd..8d38f961f402 100644 --- a/core/java/android/text/NativeLineBreaker.java +++ b/graphics/java/android/graphics/text/LineBreaker.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.text; +package android.graphics.text; import android.annotation.FloatRange; import android.annotation.IntDef; @@ -32,11 +32,57 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * A native implementation of the line breaker. - * TODO: Consider to make this class public. - * @hide + * Provides automatic line breaking for a <em>single</em> paragraph. + * + * <p> + * <pre> + * <code> + * Paint paint = new Paint(); + * String text = "Hello, Android."; + * + * // Prepare the measured text + * MeasuredText mt = new MeasuredText.Builder(text.toCharArray()) + * .addStyleRun(paint, 0, text.length(), false) // Use paint for whole paragraph. + * .build(); + * + * LineBreaker lb = new LineBreaker.Builder() + * // Use simple line breaker + * .setBreakStrategy(LineBreaker.BREAK_STRATEGY_SIMPLE) + * // Do not add hyphenation. + * .setHyphenationFrequency(LineBreaker.HYPHENATION_FREQUENCY_NONE) + * // Build the LineBreaker + * .build(); + * + * ParagraphConstraints c = new ParagraphConstraints(); + * c.setWidth(240); // Set the line wieth as 1024px + * + * // Do the line breaking + * Result r = lb.computeLineBreaks(mt, c, 0); + * + * // Compute the total height of the text. + * float totalHeight = 0; + * for (int i = 0; i < r.getLineCount(); ++i) { // iterate over the lines + * totalHeight += r.getLineDescent(i) - r.getLineAscent(i); + * } + * + * // Draw text to the canvas + * Bitmap bmp = new Bitmap.createBitmap(240, totalHeight, Bitmap.Config.ARGB_8888); + * Canvas c = new Canvas(bmp); + * float yOffset = 0f; + * int prevOffset = 0; + * for (int i = 0; i < r.getLineCount(); ++i) { // iterate over the lines + * int nextOffset = r.getLineBreakOffset(i); + * c.drawText(text, prevOffset, nextOffset, 0f, yOffset, paint); + * + * prevOffset = nextOffset; + * yOffset += r.getLineDescent(i) - r.getLineAscent(i); + * } + * </code> + * </pre> + * </p> */ -public class NativeLineBreaker { +public class LineBreaker { + /** @hide */ @IntDef(prefix = { "BREAK_STRATEGY_" }, value = { BREAK_STRATEGY_SIMPLE, BREAK_STRATEGY_HIGH_QUALITY, @@ -46,25 +92,33 @@ public class NativeLineBreaker { public @interface BreakStrategy {} /** - * Value for break strategy indicating simple line breaking. Automatic hyphens are not added - * (though soft hyphens are respected), and modifying text generally doesn't affect the layout - * before it (which yields a more consistent user experience when editing), but layout may not - * be the highest quality. + * Value for break strategy indicating simple line breaking. + * + * The line breaker puts words to the line as much as possible and breaks line if no more words + * can fit into the same line. Automatic hyphens are only added when a line has a single word + * and that word is longer than line width. This is the fastest break strategy and ideal for + * editor. */ public static final int BREAK_STRATEGY_SIMPLE = 0; /** - * Value for break strategy indicating high quality line breaking, including automatic - * hyphenation and doing whole-paragraph optimization of line breaks. + * Value for break strategy indicating high quality line breaking. + * + * With this option line breaker does whole-paragraph optimization for more readable text, and + * also applies automatic hyphenation when required. */ public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; /** - * Value for break strategy indicating balanced line breaking. The breaks are chosen to - * make all lines as close to the same length as possible, including automatic hyphenation. + * Value for break strategy indicating balanced line breaking. + * + * The line breaker does whole-paragraph optimization for making all lines similar length, and + * also applies automatic hyphenation when required. This break strategy is good for small + * screen devices such as watch screens. */ public static final int BREAK_STRATEGY_BALANCED = 2; + /** @hide */ @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = { HYPHENATION_FREQUENCY_NORMAL, HYPHENATION_FREQUENCY_FULL, @@ -74,28 +128,32 @@ public class NativeLineBreaker { public @interface HyphenationFrequency {} /** - * Value for hyphenation frequency indicating no automatic hyphenation. Useful - * for backward compatibility, and for cases where the automatic hyphenation algorithm results - * in incorrect hyphenation. Mid-word breaks may still happen when a word is wider than the - * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used - * as suggestions for potential line breaks. + * Value for hyphenation frequency indicating no automatic hyphenation. + * + * Using this option disables auto hyphenation which results in better text layout performance. + * A word may be broken without hyphens when a line has a single word and that word is longer + * than line width. Soft hyphens are ignored and will not be used as suggestions for potential + * line breaks. */ public static final int HYPHENATION_FREQUENCY_NONE = 0; /** - * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which - * is a conservative default. Useful for informal cases, such as short sentences or chat + * Value for hyphenation frequency indicating a light amount of automatic hyphenation. + * + * This hyphenation frequency is useful for informal cases, such as short sentences or chat * messages. */ public static final int HYPHENATION_FREQUENCY_NORMAL = 1; /** - * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical - * in typography. Useful for running text and where it's important to put the maximum amount of - * text in a screen with limited space. + * Value for hyphenation frequency indicating the full amount of automatic hyphenation. + * + * This hyphenation frequency is useful for running text and where it's important to put the + * maximum amount of text in a screen with limited space. */ public static final int HYPHENATION_FREQUENCY_FULL = 2; + /** @hide */ @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = { JUSTIFICATION_MODE_NONE, JUSTIFICATION_MODE_INTER_WORD @@ -114,7 +172,7 @@ public class NativeLineBreaker { public static final int JUSTIFICATION_MODE_INTER_WORD = 1; /** - * A builder class of NativeLineBreaker. + * Helper class for creating a {@link LineBreaker}. */ public static class Builder { private @BreakStrategy int mBreakStrategy = BREAK_STRATEGY_SIMPLE; @@ -123,12 +181,10 @@ public class NativeLineBreaker { private @Nullable int[] mIndents = null; /** - * Construct a builder class. - */ - public Builder() {} - - /** * Set break strategy. + * + * You can change the line breaking behavior by setting break strategy. The default value is + * {@link #BREAK_STRATEGY_SIMPLE}. */ public Builder setBreakStrategy(@BreakStrategy int breakStrategy) { mBreakStrategy = breakStrategy; @@ -137,6 +193,9 @@ public class NativeLineBreaker { /** * Set hyphenation frequency. + * + * You can change the amount of automatic hyphenation used. The default value is + * {@link #HYPHENATION_FREQUENCY_NONE}. */ public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) { mHyphenationFrequency = hyphenationFrequency; @@ -145,6 +204,10 @@ public class NativeLineBreaker { /** * Set whether the text is justified. + * + * By setting {@link #JUSTIFICATION_MODE_INTER_WORD}, the line breaker will change the + * internal parameters for justification. + * The default value is {@link #JUSTIFICATION_MODE_NONE} */ public Builder setJustified(@JustificationMode int justified) { mJustified = justified; @@ -152,9 +215,11 @@ public class NativeLineBreaker { } /** - * Set indents for entire text. + * Set indents. * - * Sets the total (left + right) indents in pixel per lines. + * The supplied array provides the total amount of indentation per line, in pixel. This + * amount is the sum of both left and right indentations. For lines past the last element in + * the array, the indentation amount of the last element is used. */ public Builder setIndents(@Nullable int[] indents) { mIndents = indents; @@ -162,11 +227,12 @@ public class NativeLineBreaker { } /** - * Returns the NativeLineBreaker with given parameters. + * Build a new LineBreaker with given parameters. + * + * You can reuse the Builder instance even after calling this method. */ - NativeLineBreaker build() { - return new NativeLineBreaker(mBreakStrategy, mHyphenationFrequency, mJustified, - mIndents); + public LineBreaker build() { + return new LineBreaker(mBreakStrategy, mHyphenationFrequency, mJustified, mIndents); } } @@ -184,8 +250,10 @@ public class NativeLineBreaker { /** * Set width for this paragraph. + * + * @see #getWidth() */ - public void setWidth(@FloatRange(from = 0.0f) float width) { + public void setWidth(@Px @FloatRange(from = 0.0f) float width) { mWidth = width; } @@ -194,9 +262,11 @@ public class NativeLineBreaker { * * @param firstWidth the line width of the starting of the paragraph * @param firstWidthLineCount the number of lines that applies the firstWidth + * @see #getFirstWidth() + * @see #getFirstWidthLineCount() */ - public void setIndent(@FloatRange(from = 0.0f) float firstWidth, - @IntRange(from = 0) int firstWidthLineCount) { + public void setIndent(@Px @FloatRange(from = 0.0f) float firstWidth, + @Px @IntRange(from = 0) int firstWidthLineCount) { mFirstWidth = firstWidth; mFirstWidthLineCount = firstWidthLineCount; } @@ -206,16 +276,21 @@ public class NativeLineBreaker { * * @param tabStops the array of pixels of tap stopping position * @param defaultTabStop pixels of the default tab stopping position + * @see #getTabStops() + * @see #getDefaultTabStop() */ - public void setTabStops(@Nullable int[] tabStops, @IntRange(from = 0) int defaultTabStop) { + public void setTabStops(@Nullable int[] tabStops, + @Px @IntRange(from = 0) int defaultTabStop) { mVariableTabStops = tabStops; mDefaultTabStop = defaultTabStop; } /** * Return the width for this paragraph in pixels. + * + * @see #setWidth(float) */ - public @FloatRange(from = 0.0f) float getWidth() { + public @Px @FloatRange(from = 0.0f) float getWidth() { return mWidth; } @@ -224,7 +299,7 @@ public class NativeLineBreaker { * * @see #setIndent(float, int) */ - public @FloatRange(from = 0.0f) float getFirstWidth() { + public @Px @FloatRange(from = 0.0f) float getFirstWidth() { return mFirstWidth; } @@ -233,7 +308,7 @@ public class NativeLineBreaker { * * @see #setIndent(float, int) */ - public @IntRange(from = 0) int getFirstWidthLineCount() { + public @Px @IntRange(from = 0) int getFirstWidthLineCount() { return mFirstWidthLineCount; } @@ -251,13 +326,14 @@ public class NativeLineBreaker { * * @see #setTabStop(int[], int) */ - public @IntRange(from = 0) int getDefaultTabStop() { + public @Px @IntRange(from = 0) int getDefaultTabStop() { return mDefaultTabStop; } } /** - * A result object of a line breaking + * Holds the result of the {@link LineBreaker#computeLineBreaks line breaking algorithm}. + * @see LineBreaker#computeLineBreaks */ public static class Result { // Following two contstant must be synced with minikin's line breaker. @@ -274,7 +350,7 @@ public class NativeLineBreaker { } /** - * Returns a number of line count. + * Returns the number of lines in the paragraph. * * @return number of lines */ @@ -283,7 +359,7 @@ public class NativeLineBreaker { } /** - * Returns a break offset of the line. + * Returns character offset of the break for a given line. * * @param lineIndex an index of the line. * @return the break offset. @@ -293,17 +369,17 @@ public class NativeLineBreaker { } /** - * Returns a width of the line in pixels. + * Returns width of a given line in pixels. * * @param lineIndex an index of the line. - * @return a width of the line in pixexls + * @return width of the line in pixels */ public @Px float getLineWidth(@IntRange(from = 0) int lineIndex) { return nGetLineWidth(mPtr, lineIndex); } /** - * Returns an entier font ascent of the line in pixels. + * Returns font ascent of the line in pixels. * * @param lineIndex an index of the line. * @return an entier font ascent of the line in pixels. @@ -313,7 +389,7 @@ public class NativeLineBreaker { } /** - * Returns an entier font descent of the line in pixels. + * Returns font descent of the line in pixels. * * @param lineIndex an index of the line. * @return an entier font descent of the line in pixels. @@ -337,6 +413,7 @@ public class NativeLineBreaker { * * @param lineIndex an index of the line. * @return a packed hyphen edit for the line. + * * @see android.text.Hyphenator#unpackStartHyphenEdit(int) * @see android.text.Hyphenator#unpackEndHyphenEdit(int) * @see android.text.Hyphenator#packHyphenEdit(int,int) @@ -347,14 +424,14 @@ public class NativeLineBreaker { } private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( - NativeLineBreaker.class.getClassLoader(), nGetReleaseFunc(), 64); + LineBreaker.class.getClassLoader(), nGetReleaseFunc(), 64); private final long mNativePtr; /** * Use Builder instead. */ - private NativeLineBreaker(@BreakStrategy int breakStrategy, + private LineBreaker(@BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, @JustificationMode int justify, @Nullable int[] indents) { mNativePtr = nInit(breakStrategy, hyphenationFrequency, @@ -372,7 +449,7 @@ public class NativeLineBreaker { * @param lineNumber a line number of this paragraph */ public Result computeLineBreaks( - @NonNull NativeMeasuredParagraph measuredPara, + @NonNull MeasuredText measuredPara, @NonNull ParagraphConstraints constraints, @IntRange(from = 0) int lineNumber) { return new Result(nComputeLineBreaks( diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java new file mode 100644 index 000000000000..36e7028915f3 --- /dev/null +++ b/graphics/java/android/graphics/text/MeasuredText.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2010 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.graphics.text; + +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Px; +import android.graphics.Paint; +import android.graphics.Rect; + +import com.android.internal.util.Preconditions; + +import dalvik.annotation.optimization.CriticalNative; + +import libcore.util.NativeAllocationRegistry; + +/** + * Result of text shaping of the single paragraph string. + */ +public class MeasuredText { + private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( + MeasuredText.class.getClassLoader(), nGetReleaseFunc(), 1024); + + private long mNativePtr; + private @NonNull char[] mChars; + + // Use builder instead. + private MeasuredText(long ptr, @NonNull char[] chars) { + mNativePtr = ptr; + mChars = chars; + } + + /** + * Returns the characters in the paragraph used to compute this MeasuredText instance. + */ + public @NonNull char[] getChars() { + return mChars; + } + + /** + * Returns the width of a given range. + * + * @param start an inclusive start index of the range + * @param end an exclusive end index of the range + */ + public @FloatRange(from = 0.0) @Px float getWidth( + @IntRange(from = 0) int start, @IntRange(from = 0) int end) { + Preconditions.checkArgument(0 <= start && start <= mChars.length, + "start(" + start + ") must be 0 <= start <= " + mChars.length); + Preconditions.checkArgument(0 <= end && end <= mChars.length, + "end(" + end + ") must be 0 <= end <= " + mChars.length); + Preconditions.checkArgument(start <= end, + "start(" + start + ") is larger than end(" + end + ")"); + return nGetWidth(mNativePtr, start, end); + } + + /** + * Returns a memory usage of the native object. + * + * @hide + */ + public int getMemoryUsage() { + return nGetMemoryUsage(mNativePtr); + } + + /** + * Retrieves the boundary box of the given range + * + * @param start an inclusive start index of the range + * @param end an exclusive end index of the range + * @param rect an output parameter + */ + public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end, + @NonNull Rect rect) { + Preconditions.checkArgument(0 <= start && start <= mChars.length, + "start(" + start + ") must be 0 <= start <= " + mChars.length); + Preconditions.checkArgument(0 <= end && end <= mChars.length, + "end(" + end + ") must be 0 <= end <= " + mChars.length); + Preconditions.checkArgument(start <= end, + "start(" + start + ") is larger than end(" + end + ")"); + Preconditions.checkNotNull(rect); + nGetBounds(mNativePtr, mChars, start, end, rect); + } + + /** + * Returns the width of the character at the given offset. + * + * @param offset an offset of the character. + */ + public @FloatRange(from = 0.0f) @Px float getCharWidthAt(@IntRange(from = 0) int offset) { + Preconditions.checkArgument(0 <= offset && offset < mChars.length, + "offset(" + offset + ") is larger than text length: " + mChars.length); + return nGetCharWidthAt(mNativePtr, offset); + } + + /** + * Returns a native pointer of the underlying native object. + * + * @hide + */ + public long getNativePtr() { + return mNativePtr; + } + + @CriticalNative + private static native float nGetWidth(/* Non Zero */ long nativePtr, + @IntRange(from = 0) int start, + @IntRange(from = 0) int end); + + @CriticalNative + private static native /* Non Zero */ long nGetReleaseFunc(); + + @CriticalNative + private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr); + + private static native void nGetBounds(long nativePtr, char[] buf, int start, int end, + Rect rect); + + @CriticalNative + private static native float nGetCharWidthAt(long nativePtr, int offset); + + /** + * Helper class for creating a {@link MeasuredText}. + */ + public static class Builder { + private long mNativePtr; + + private final @NonNull char[] mText; + private boolean mComputeHyphenation = false; + private boolean mComputeLayout = true; + + /** + * Construct a builder. + * + * The MeasuredText returned by build method will hold a reference of the text. Developer is + * not supposed to modify the text. + * + * @param text a text + */ + public Builder(@NonNull char[] text) { + Preconditions.checkNotNull(text); + mText = text; + mNativePtr = nInitBuilder(); + } + + /** + * Apply styles to the given range. + * + * @param paint a paint + * @param start an inclusive start index of the range + * @param end an exclusive end index of the range + * @param isRtl true if the text is in RTL context, otherwise false. + */ + public Builder addStyleRun(@NonNull Paint paint, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl) { + Preconditions.checkNotNull(paint); + nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl); + return this; + } + + /** + * Used to inform the text layout that the given range is replaced with the object of given + * width. + * + * Informs the layout engine that the given range should not be processed, instead the + * provided width should be used for calculating the width of that range. + * + * @param start an inclusive start index of the range + * @param end an exclusive end index of the range + * @param width a replacement width of the range + */ + public Builder addReplacementRun(@NonNull Paint paint, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, + @FloatRange(from = 0) float width) { + nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width); + return this; + } + + /** + * By passing true to this method, the build method will compute all possible hyphenation + * pieces as well. + * + * If you don't want to use automatic hyphenation, you can pass false to this method and + * save the computation time of hyphenation. The default value is false. + * + * Even if you pass false to this method, you can still enable automatic hyphenation of + * LineBreaker but line break computation becomes slower. + * + * @param computeHyphenation true if you want to use automatic hyphenations. + */ + public Builder setComputeHyphenation(boolean computeHyphenation) { + mComputeHyphenation = computeHyphenation; + return this; + } + + /** + * By passing true to this method, the build method will compute all full layout + * information. + * + * If you don't use {@link MeasuredText#getBounds(int,int,android.graphics.Rect)}, you can + * pass false to this method and save the memory spaces. The default value is true. + * + * Even if you pass false to this method, you can still call getBounds but it becomes + * slower. + * + * @param computeLayout true if you want to retrieve full layout info, e.g. bbox. + */ + public Builder setComputeLayout(boolean computeLayout) { + mComputeLayout = computeLayout; + return this; + } + + /** + * Creates a MeasuredText. + * + * Once you called build() method, you can't reuse the Builder class again. + * @throws IllegalStateException if this Builder is reused. + */ + public MeasuredText build() { + if (mNativePtr == 0) { + throw new IllegalStateException("Builder can not be reused."); + } + try { + long ptr = nBuildMeasuredText(mNativePtr, mText, mComputeHyphenation, + mComputeLayout); + MeasuredText res = new MeasuredText(ptr, mText); + sRegistry.registerNativeAllocation(res, ptr); + return res; + } finally { + nFreeBuilder(mNativePtr); + mNativePtr = 0; + } + } + + private static native /* Non Zero */ long nInitBuilder(); + + /** + * Apply style to make native measured text. + * + * @param nativeBuilderPtr The native MeasuredParagraph builder pointer. + * @param paintPtr The native paint pointer to be applied. + * @param start The start offset in the copied buffer. + * @param end The end offset in the copied buffer. + * @param isRtl True if the text is RTL. + */ + private static native void nAddStyleRun(/* Non Zero */ long nativeBuilderPtr, + /* Non Zero */ long paintPtr, + @IntRange(from = 0) int start, + @IntRange(from = 0) int end, + boolean isRtl); + /** + * Apply ReplacementRun to make native measured text. + * + * @param nativeBuilderPtr The native MeasuredParagraph builder pointer. + * @param paintPtr The native paint pointer to be applied. + * @param start The start offset in the copied buffer. + * @param end The end offset in the copied buffer. + * @param width The width of the replacement. + */ + private static native void nAddReplacementRun(/* Non Zero */ long nativeBuilderPtr, + /* Non Zero */ long paintPtr, + @IntRange(from = 0) int start, + @IntRange(from = 0) int end, + @FloatRange(from = 0) float width); + + private static native long nBuildMeasuredText( + /* Non Zero */ long nativeBuilderPtr, + @NonNull char[] text, + boolean computeHyphenation, + boolean computeLayout); + + private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr); + } +} diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index 8f58f74d4652..66a547723b2f 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -39,7 +39,7 @@ using base::unique_fd; static const std::string kResourcesArsc("resources.arsc"); -ApkAssets::ApkAssets(void* unmanaged_handle, const std::string& path) +ApkAssets::ApkAssets(ZipArchiveHandle unmanaged_handle, const std::string& path) : zip_handle_(unmanaged_handle, ::CloseArchive), path_(path) { } diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index 69702e314442..db2d0382bcf6 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -27,6 +27,9 @@ #include "androidfw/LoadedArsc.h" #include "androidfw/misc.h" +struct ZipArchive; +typedef ZipArchive* ZipArchiveHandle; + namespace android { class LoadedIdmap; @@ -88,9 +91,9 @@ class ApkAssets { // Creates an Asset from any file on the file system. static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path); - ApkAssets(void* unmanaged_handle, const std::string& path); + ApkAssets(ZipArchiveHandle unmanaged_handle, const std::string& path); - using ZipArchivePtr = std::unique_ptr<void, void(*)(void*)>; + using ZipArchivePtr = std::unique_ptr<ZipArchive, void(*)(ZipArchiveHandle)>; ZipArchivePtr zip_handle_; const std::string path_; diff --git a/libs/androidfw/include/androidfw/ZipFileRO.h b/libs/androidfw/include/androidfw/ZipFileRO.h index 03154d04def1..c221e3b7aeae 100644 --- a/libs/androidfw/include/androidfw/ZipFileRO.h +++ b/libs/androidfw/include/androidfw/ZipFileRO.h @@ -41,7 +41,8 @@ #include <unistd.h> #include <time.h> -typedef void* ZipArchiveHandle; +struct ZipArchive; +typedef ZipArchive* ZipArchiveHandle; namespace android { diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp index bc742b0c5a63..df5f45618070 100644 --- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp +++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp @@ -35,23 +35,6 @@ SkBitmap createSkBitmap(int width, int height) { return bitmap; } -/** - * 1x1 bitmaps must not be optimized into solid color shaders, since HWUI can't - * compose/render color shaders - */ -TEST(SkiaBehavior, CreateBitmapShader1x1) { - SkBitmap origBitmap = createSkBitmap(1, 1); - sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(origBitmap, kNever_SkCopyPixelsMode); - sk_sp<SkShader> s = - image->makeShader(SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, nullptr); - - SkBitmap bitmap; - SkShader::TileMode xy[2]; - ASSERT_TRUE(s->isABitmap(&bitmap, nullptr, xy)) - << "1x1 bitmap shader must query as bitmap shader"; - EXPECT_EQ(origBitmap.pixelRef(), bitmap.pixelRef()); -} - TEST(SkiaBehavior, genIds) { SkBitmap bitmap = createSkBitmap(100, 100); uint32_t genId = bitmap.getGenerationID(); diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 5604ffd83deb..084b2049e30b 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -461,12 +461,12 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override void process() { mVolume = volume; - _setVolume(volume, volume); + _setVolume(volume); } }); } - private native void _setVolume(float leftVolume, float rightVolume); + private native void _setVolume(float volume); /** * Returns the current volume of this player to this player. diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java index a7eb30d0f596..0c1d1a2fc8d2 100644 --- a/media/java/android/media/update/ApiLoader.java +++ b/media/java/android/media/update/ApiLoader.java @@ -16,14 +16,64 @@ package android.media.update; +import android.app.ActivityManager; +import android.app.AppGlobals; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; +import android.os.RemoteException; +import android.os.UserHandle; + +import com.android.internal.annotations.GuardedBy; + +import dalvik.system.PathClassLoader; + +import java.io.File; + /** * @hide */ public final class ApiLoader { + @GuardedBy("this") + private static StaticProvider sMediaUpdatable; + + private static final String UPDATE_PACKAGE = "com.android.media.update"; + private static final String UPDATE_CLASS = "com.android.media.update.ApiFactory"; + private static final String UPDATE_METHOD = "initialize"; + private static final boolean REGISTER_UPDATE_DEPENDENCY = true; + private ApiLoader() { } public static StaticProvider getProvider() { - throw new RuntimeException("Use MediaSession/Browser instead of" - + " hidden MediaSession2/Browser2 APIs."); + try { + return getMediaUpdatable(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (NameNotFoundException | ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + // TODO This method may do I/O; Ensure it does not violate (emit warnings in) strict mode. + private static synchronized StaticProvider getMediaUpdatable() + throws NameNotFoundException, ReflectiveOperationException, RemoteException { + if (sMediaUpdatable != null) return sMediaUpdatable; + + // TODO Figure out when to use which package (query media update service) + int flags = Build.IS_DEBUGGABLE ? 0 : PackageManager.MATCH_SYSTEM_ONLY; + ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo( + UPDATE_PACKAGE, flags, UserHandle.myUserId()); + + if (REGISTER_UPDATE_DEPENDENCY) { + // Register a dependency to the updatable in order to be killed during updates + ActivityManager.getService().addPackageDependency(ai.packageName); + } + + ClassLoader classLoader = new PathClassLoader(ai.sourceDir, + ai.nativeLibraryDir + File.pathSeparator + System.getProperty("java.library.path"), + ClassLoader.getSystemClassLoader().getParent()); + return sMediaUpdatable = (StaticProvider) classLoader.loadClass(UPDATE_CLASS) + .getMethod(UPDATE_METHOD, ApplicationInfo.class).invoke(null, ai); } } diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp index b52da362beff..352df811d42f 100644 --- a/media/jni/android_media_MediaPlayer2.cpp +++ b/media/jni/android_media_MediaPlayer2.cpp @@ -974,15 +974,15 @@ android_media_MediaPlayer2_isLooping(JNIEnv *env, jobject thiz) } static void -android_media_MediaPlayer2_setVolume(JNIEnv *env, jobject thiz, jfloat leftVolume, jfloat rightVolume) +android_media_MediaPlayer2_setVolume(JNIEnv *env, jobject thiz, jfloat volume) { - ALOGV("setVolume: left %f right %f", (float) leftVolume, (float) rightVolume); + ALOGV("setVolume: volume %f", (float) volume); sp<MediaPlayer2> mp = getMediaPlayer(env, thiz); if (mp == NULL ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } - process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL ); + process_media_player_call( env, thiz, mp->setVolume((float) volume), NULL, NULL ); } static jbyteArray @@ -1481,7 +1481,7 @@ static const JNINativeMethod gMethods[] = { {"getParameter", "(I)Ljava/lang/Object;", (void *)android_media_MediaPlayer2_getParameter}, {"setLooping", "(Z)V", (void *)android_media_MediaPlayer2_setLooping}, {"isLooping", "()Z", (void *)android_media_MediaPlayer2_isLooping}, - {"_setVolume", "(FF)V", (void *)android_media_MediaPlayer2_setVolume}, + {"_setVolume", "(F)V", (void *)android_media_MediaPlayer2_setVolume}, {"_invoke", "([B)[B", (void *)android_media_MediaPlayer2_invoke}, {"native_init", "()V", (void *)android_media_MediaPlayer2_native_init}, {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer2_native_setup}, diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java index 8fed367f3773..f2de9ecd8f5d 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java @@ -54,9 +54,14 @@ public class InstallStart extends Activity { Intent intent = getIntent(); String callingPackage = getCallingPackage(); + final boolean isSessionInstall = + PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction()); + // If the activity was started via a PackageInstaller session, we retrieve the calling // package from that session - int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1); + final int sessionId = (isSessionInstall + ? intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1) + : -1); if (callingPackage == null && sessionId != -1) { PackageInstaller packageInstaller = getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId); @@ -99,7 +104,7 @@ public class InstallStart extends Activity { nextActivity.putExtra(PackageInstallerActivity.EXTRA_ORIGINAL_SOURCE_INFO, sourceInfo); nextActivity.putExtra(Intent.EXTRA_ORIGINATING_UID, originatingUid); - if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) { + if (isSessionInstall) { nextActivity.setClass(this, PackageInstallerActivity.class); } else { Uri packageUri = intent.getData(); diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java index 8c29a2520390..441dbac24928 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -16,7 +16,7 @@ */ package com.android.packageinstaller; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.Manifest; import android.annotation.NonNull; @@ -281,7 +281,7 @@ public class PackageInstallerActivity extends AlertActivity { @Override protected void onCreate(Bundle icicle) { - getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); super.onCreate(null); diff --git a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java index 7306d968a709..e407d7239546 100644 --- a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java +++ b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java @@ -187,17 +187,17 @@ public class HelpUtils { if (sendPackageName && includePackageName) { String[] packageNameKey = - {resources.getString(android.R.string.config_help_package_name_key)}; + {resources.getString(android.R.string.config_helpPackageNameKey)}; String[] packageNameValue = - {resources.getString(android.R.string.config_help_package_name_value)}; + {resources.getString(android.R.string.config_helpPackageNameValue)}; String helpIntentExtraKey = - resources.getString(android.R.string.config_help_intent_extra_key); + resources.getString(android.R.string.config_helpIntentExtraKey); String helpIntentNameKey = - resources.getString(android.R.string.config_help_intent_name_key); + resources.getString(android.R.string.config_helpIntentNameKey); String feedbackIntentExtraKey = - resources.getString(android.R.string.config_feedback_intent_extra_key); + resources.getString(android.R.string.config_feedbackIntentExtraKey); String feedbackIntentNameKey = - resources.getString(android.R.string.config_feedback_intent_name_key); + resources.getString(android.R.string.config_feedbackIntentNameKey); intent.putExtra(helpIntentExtraKey, packageNameKey); intent.putExtra(helpIntentNameKey, packageNameValue); intent.putExtra(feedbackIntentExtraKey, packageNameKey); diff --git a/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml b/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml index 0f02abd94216..0748192fb1fc 100644 --- a/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml +++ b/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml @@ -15,7 +15,7 @@ --> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/restricted_icon" - android:layout_width="@*android:dimen/config_restricted_icon_size" - android:layout_height="@*android:dimen/config_restricted_icon_size" + android:layout_width="@*android:dimen/config_restrictedIconSize" + android:layout_height="@*android:dimen/config_restrictedIconSize" android:tint="?android:attr/colorAccent" android:src="@*android:drawable/ic_info" /> diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java index b87c9e8de1b2..e278c10a2c59 100644 --- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java +++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java @@ -91,13 +91,7 @@ public class RestrictedLockUtils { public static boolean isCurrentUserOrProfile(Context context, int userId) { UserManager um = context.getSystemService(UserManager.class); - int[] userIds = um.getProfileIds(UserHandle.myUserId(), true); - for (int i = 0; i < userIds.length; i++) { - if (userIds[i] == userId) { - return true; - } - } - return false; + return um.getUserProfiles().contains(UserHandle.of(userId)); } public static class EnforcedAdmin { diff --git a/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml b/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml index af30425a511c..cbebbb32dc89 100644 --- a/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml +++ b/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml @@ -18,11 +18,14 @@ <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:paddingMode="stack"> <item> - <shape> + <shape + android:tint="?android:attr/colorForeground"> <corners android:radius="20dp"/> + <solid + android:color="@android:color/transparent"/> <stroke - android:color="?android:attr/textColorSecondary" + android:color="#1f000000" android:width="1dp"/> <size android:height="32dp"/> diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml index e1f6cdf57101..5dbcb7952e88 100644 --- a/packages/SettingsLib/res/layout/restricted_switch_widget.xml +++ b/packages/SettingsLib/res/layout/restricted_switch_widget.xml @@ -16,8 +16,8 @@ <merge xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/restricted_icon" - android:layout_width="@*android:dimen/config_restricted_icon_size" - android:layout_height="@*android:dimen/config_restricted_icon_size" + android:layout_width="@*android:dimen/config_restrictedIconSize" + android:layout_height="@*android:dimen/config_restrictedIconSize" android:tint="?android:attr/colorAccent" android:src="@*android:drawable/ic_info" android:gravity="end|center_vertical" /> diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java index f57122e6708d..1457fcfadc89 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java @@ -58,7 +58,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { public static Drawable getRestrictedPadlock(Context context) { Drawable restrictedPadlock = context.getDrawable(android.R.drawable.ic_info); final int iconSize = context.getResources().getDimensionPixelSize( - android.R.dimen.config_restricted_icon_size); + android.R.dimen.config_restrictedIconSize); TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent}); int colorAccent = ta.getColor(0, 0); diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java b/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java index 3102239c2c9e..3c451127508d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java @@ -25,7 +25,6 @@ import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.RemoteException; -import android.os.UserHandle; import android.util.IconDrawableFactory; import com.android.settingslib.widget.CandidateInfo; @@ -46,8 +45,8 @@ public class DefaultAppInfo extends CandidateInfo { this(context, pm, uid, cn, null /* summary */, true /* enabled */); } - public DefaultAppInfo(Context context, PackageManager pm, PackageItemInfo info) { - this(context, pm, info, null /* summary */, true /* enabled */); + public DefaultAppInfo(Context context, PackageManager pm, int uid, PackageItemInfo info) { + this(context, pm, uid, info, null /* summary */, true /* enabled */); } public DefaultAppInfo(Context context, PackageManager pm, int uid, ComponentName cn, @@ -61,12 +60,12 @@ public class DefaultAppInfo extends CandidateInfo { this.summary = summary; } - public DefaultAppInfo(Context context, PackageManager pm, PackageItemInfo info, + public DefaultAppInfo(Context context, PackageManager pm, int uid, PackageItemInfo info, String summary, boolean enabled) { super(enabled); mContext = context; mPm = pm; - userId = UserHandle.myUserId(); + userId = uid; packageItemInfo = info; componentName = null; this.summary = summary; diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 750a8438c00d..a2e30df9ac5c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -60,11 +60,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private short mRssi; private final List<LocalBluetoothProfile> mProfiles = - new ArrayList<LocalBluetoothProfile>(); + Collections.synchronizedList(new ArrayList<>()); // List of profiles that were previously in mProfiles, but have been removed private final List<LocalBluetoothProfile> mRemovedProfiles = - new ArrayList<LocalBluetoothProfile>(); + Collections.synchronizedList(new ArrayList<>()); // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP private boolean mLocalNapRoleConnected; diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java index 1091e1601b89..36b70dfe2297 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java @@ -70,17 +70,17 @@ public class HelpUtilsTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - when(mContext.getResources().getString(R.string.config_help_package_name_key)) + when(mContext.getResources().getString(R.string.config_helpPackageNameKey)) .thenReturn(PACKAGE_NAME_KEY); - when(mContext.getResources().getString(R.string.config_help_package_name_value)) + when(mContext.getResources().getString(R.string.config_helpPackageNameValue)) .thenReturn(PACKAGE_NAME_VALUE); - when(mContext.getResources().getString(R.string.config_help_intent_extra_key)) + when(mContext.getResources().getString(R.string.config_helpIntentExtraKey)) .thenReturn(HELP_INTENT_EXTRA_KEY); - when(mContext.getResources().getString(R.string.config_help_intent_name_key)) + when(mContext.getResources().getString(R.string.config_helpIntentNameKey)) .thenReturn(HELP_INTENT_NAME_KEY); - when(mContext.getResources().getString(R.string.config_feedback_intent_extra_key)) + when(mContext.getResources().getString(R.string.config_feedbackIntentExtraKey)) .thenReturn(FEEDBACK_INTENT_EXTRA_KEY); - when(mContext.getResources().getString(R.string.config_feedback_intent_name_key)) + when(mContext.getResources().getString(R.string.config_feedbackIntentNameKey)) .thenReturn(FEEDBACK_INTENT_NAME_KEY); when(mActivity.getPackageManager()).thenReturn(mPackageManager); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java index 01f0d78ede1a..a92a2dd8c11a 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java @@ -18,8 +18,8 @@ package com.android.settingslib.applications; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -72,7 +72,7 @@ public class DefaultAppInfoTest { @Test public void initInfoWithActivityInfo_shouldLoadInfo() { mPackageItemInfo.packageName = "test"; - mInfo = new DefaultAppInfo(mContext, mPackageManager, mPackageItemInfo); + mInfo = new DefaultAppInfo(mContext, mPackageManager, 0 /* uid */, mPackageItemInfo); mInfo.loadLabel(); Drawable icon = mInfo.loadIcon(); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 8745a330311a..da1354be63d2 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -662,6 +662,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.ANGLE_ENABLED_APP, GlobalSettingsProto.Gpu.ANGLE_ENABLED_APP); + dumpSetting(s, p, + Settings.Global.GPU_DEBUG_LAYER_APP, + GlobalSettingsProto.Gpu.DEBUG_LAYER_APP); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index dcc6cbafe41d..822c39b6a71d 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -56,6 +56,7 @@ <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> + <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" /> <!-- Development tool permissions granted to the shell. --> <uses-permission android:name="android.permission.SET_DEBUG_APP" /> <uses-permission android:name="android.permission.SET_PROCESS_LIMIT" /> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RotationWatcher.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RotationWatcher.java index 5a28a5e28d91..7c8c23eba73b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RotationWatcher.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RotationWatcher.java @@ -48,7 +48,7 @@ public abstract class RotationWatcher { if (!mIsWatching) { try { WindowManagerGlobal.getWindowManagerService().watchRotation(mWatcher, - mContext.getDisplay().getDisplayId()); + mContext.getDisplayId()); mIsWatching = true; } catch (RemoteException e) { Log.w(TAG, "Failed to set rotation watcher", e); diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java index 198a4e6cedb8..b1463a3c53ea 100644 --- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java +++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java @@ -143,9 +143,6 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { mSeparatedView.setBackground(mSeparatedViewBackground); updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding()); mOldHeight = mList.getMeasuredHeight(); - mList.addOnLayoutChangeListener( - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> - updatePosition()); updateRotation(); } else { return; @@ -155,6 +152,8 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { if (newHeight != mOldHeight) { animateChild(mOldHeight, newHeight); } + + post(() -> updatePaddingAndGravityIfTooTall()); post(() -> updatePosition()); } @@ -241,7 +240,7 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { separatedViewLayoutParams.gravity = rotateGravityRight(separatedViewLayoutParams.gravity); mSeparatedView.setLayoutParams(separatedViewLayoutParams); - setGravity(p.gravity); + setGravity(rotateGravityRight(getGravity())); } private void swapDimens(View v) { @@ -299,7 +298,7 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { separatedViewLayoutParams.gravity = rotateGravityLeft(separatedViewLayoutParams.gravity); mSeparatedView.setLayoutParams(separatedViewLayoutParams); - setGravity(p.gravity); + setGravity(rotateGravityLeft(getGravity())); } private int rotateGravityLeft(int gravity) { @@ -447,6 +446,46 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { mAnimator.start(); } + // If current power menu height larger then screen height, remove padding to break power menu + // alignment and set menu center vertical within the screen. + private void updatePaddingAndGravityIfTooTall() { + int defaultTopPadding; + int viewsTotalHeight; + int separatedViewTopMargin; + int screenHeight; + int totalHeight; + int targetGravity; + MarginLayoutParams params = (MarginLayoutParams) mSeparatedView.getLayoutParams(); + switch (RotationUtils.getRotation(getContext())) { + case RotationUtils.ROTATION_LANDSCAPE: + defaultTopPadding = getPaddingLeft(); + viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth(); + separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0; + screenHeight = getMeasuredWidth(); + targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP; + break; + case RotationUtils.ROTATION_SEASCAPE: + defaultTopPadding = getPaddingRight(); + viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth(); + separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0; + screenHeight = getMeasuredWidth(); + targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM; + break; + default: // Portrait + defaultTopPadding = getPaddingTop(); + viewsTotalHeight = mList.getMeasuredHeight() + mSeparatedView.getMeasuredHeight(); + separatedViewTopMargin = mHasSeparatedButton ? params.topMargin : 0; + screenHeight = getMeasuredHeight(); + targetGravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT; + break; + } + totalHeight = defaultTopPadding + viewsTotalHeight + separatedViewTopMargin; + if (totalHeight >= screenHeight) { + setPadding(0, 0, 0, 0); + setGravity(targetGravity); + } + } + @Override public ViewOutlineProvider getOutlineProvider() { return super.getOutlineProvider(); diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java index d351c4f3e3e6..1bf87506ab0c 100644 --- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java @@ -259,6 +259,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis @Override public void onServiceConnected(ComponentName name, IBinder service) { mHandler.removeCallbacks(mDeferredConnectionCallback); + mCurrentBoundedUserId = mDeviceProvisionedController.getCurrentUser(); mConnectionBackoffAttempts = 0; mOverviewProxy = IOverviewProxy.Stub.asInterface(service); // Listen for launcher's death @@ -269,7 +270,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } try { mOverviewProxy.onBind(mSysUiProxy); - mCurrentBoundedUserId = mDeviceProvisionedController.getCurrentUser(); } catch (RemoteException e) { mCurrentBoundedUserId = -1; Log.e(TAG_OPS, "Failed to call onBind()", e); diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java index 6d790668995e..449ed8c3bcdb 100644 --- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java @@ -14,7 +14,7 @@ package com.android.systemui; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.app.Activity; import android.app.AlertDialog; @@ -69,7 +69,7 @@ public class SlicePermissionActivity extends Activity implements OnClickListener .setPositiveButton(R.string.slice_permission_allow, this) .setOnDismissListener(this) .create(); - dialog.getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + dialog.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); dialog.show(); TextView t1 = dialog.getWindow().getDecorView().findViewById(R.id.text1); t1.setText(getString(R.string.slice_permission_text_1, app2)); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java index 4a6786832df0..df763151cdd7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java @@ -16,7 +16,7 @@ package com.android.systemui.media; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.app.Activity; import android.app.AlertDialog; @@ -151,7 +151,7 @@ public class MediaProjectionPermissionActivity extends Activity ((CheckBox) mDialog.findViewById(R.id.remember)).setOnCheckedChangeListener(this); final Window w = mDialog.getWindow(); w.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - w.addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); mDialog.show(); } diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java index 774567ef8bb1..95029c013ab6 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java @@ -26,6 +26,10 @@ import com.android.systemui.shared.plugins.PluginManagerImpl; public class PluginInitializerImpl implements PluginInitializer { + /** + * True if WTFs should lead to crashes + */ + private static final boolean WTFS_SHOULD_CRASH = false; private boolean mWtfsSet; @Override @@ -52,7 +56,7 @@ public class PluginInitializerImpl implements PluginInitializer { @Override public void handleWtfs() { - if (!mWtfsSet) { + if (WTFS_SHOULD_CRASH && !mWtfsSet) { mWtfsSet = true; Log.setWtfHandler(new Log.TerribleFailureHandler() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java index 2c384d0f4d80..21a33b0271db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT; + import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; @@ -85,6 +87,7 @@ public final class AmbientPulseManager extends AlertingNotificationManager { for (OnAmbientChangedListener listener : mListeners) { listener.onAmbientStateChanged(entry, false); } + entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 0c5f39198b4f..a00eac4adea0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -19,14 +19,14 @@ package com.android.systemui.statusbar; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.admin.DevicePolicyManager; -import android.hardware.biometrics.BiometricSourceType; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; import android.content.res.ColorStateList; +import android.content.res.Resources; import android.graphics.Color; +import android.hardware.biometrics.BiometricSourceType; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.os.BatteryManager; @@ -106,6 +106,7 @@ public class KeyguardIndicationController { private final DevicePolicyManager mDevicePolicyManager; private boolean mDozing; + private float mDarkAmount; /** * Creates a new KeyguardIndicationController and registers callbacks. @@ -298,6 +299,15 @@ public class KeyguardIndicationController { if (mVisible) { // Walk down a precedence-ordered list of what indication // should be shown based on user or device state + if (mDozing) { + if (!TextUtils.isEmpty(mTransientIndication)) { + mTextView.setTextColor(Color.WHITE); + mTextView.switchIndication(mTransientIndication); + } + updateAlphas(); + return; + } + KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); int userId = KeyguardUpdateMonitor.getCurrentUser(); String trustGrantedIndication = getTrustGrantedIndication(); @@ -335,6 +345,14 @@ public class KeyguardIndicationController { } } + private void updateAlphas() { + if (!TextUtils.isEmpty(mTransientIndication)) { + mTextView.setAlpha(1f); + } else { + mTextView.setAlpha(1f - mDarkAmount); + } + } + // animates textView - textView moves up and bounces down private void animateText(KeyguardIndicationTextView textView, String indication) { int yTranslation = mContext.getResources().getInteger( @@ -492,6 +510,14 @@ public class KeyguardIndicationController { pw.println(" computePowerIndication(): " + computePowerIndication()); } + public void setDarkAmount(float darkAmount) { + if (mDarkAmount == darkAmount) { + return; + } + mDarkAmount = darkAmount; + updateAlphas(); + } + protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback { public static final int HIDE_DELAY_MS = 5000; private int mLastSuccessiveErrorMessage = -1; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index e89e6e89bc07..2db99453e36c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -256,9 +256,9 @@ public class NotificationMediaManager implements Dumpable { private boolean isMediaNotification(NotificationData.Entry entry) { // TODO: confirm that there's a valid media key - return entry.getExpandedContentView() != null && - entry.getExpandedContentView() - .findViewById(com.android.internal.R.id.media_actions) != null; + return entry.row.getExpandedContentView() != null + && entry.row.getExpandedContentView().findViewById( + com.android.internal.R.id.media_actions) != null; } private void clearCurrentMediaNotificationSession() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java index d6719f0a03e1..78a5817c32b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.GuardedBy; +import com.android.systemui.statusbar.phone.StatusBar; import java.lang.annotation.Retention; import java.util.ArrayList; import java.util.Comparator; @@ -39,6 +40,7 @@ public class StatusBarStateController { = (o1, o2) -> Integer.compare(o1.rank, o2.rank); private final ArrayList<RankedListener> mListeners = new ArrayList<>(); + private boolean mIsDozing; private int mState; private int mLastState; private boolean mLeaveOpenOnKeyguardHide; @@ -57,6 +59,11 @@ public class StatusBarStateController { return mState; } + /** + * Update the status bar state + * @param state see {@link StatusBarState} for valid options + * @return {@code true} if the state changed, else {@code false} + */ public boolean setState(int state) { if (state > MAX_STATE || state < MIN_STATE) { throw new IllegalArgumentException("Invalid state " + state); @@ -82,6 +89,32 @@ public class StatusBarStateController { return true; } + public boolean isDozing() { + return mIsDozing; + } + + /** + * Update the dozing state from {@link StatusBar}'s perspective + * @param isDozing well, are we dozing? + * @return {@code true} if the state changed, else {@code false} + */ + @SuppressWarnings("UnusedReturnValue") + public boolean setIsDozing(boolean isDozing) { + if (mIsDozing == isDozing) { + return false; + } + + mIsDozing = isDozing; + + synchronized (mListeners) { + for (RankedListener rl : new ArrayList<>(mListeners)) { + rl.listener.onDozingChanged(isDozing); + } + } + + return true; + } + public boolean goingToFullShade() { return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide; } @@ -144,23 +177,49 @@ public class StatusBarStateController { return StatusBarState.toShortString(state); } + private class RankedListener { + private final StateListener listener; + private final int rank; + + private RankedListener(StateListener l, int r) { + listener = l; + rank = r; + } + } + + /** + * Listener for StatusBarState updates + */ public interface StateListener { + + /** + * Callback before the new state is applied, for those who need to preempt the change + * @param oldState state before the change + * @param newState new state to be applied in {@link #onStateChanged} + */ public default void onStatePreChange(int oldState, int newState) { } + /** + * Callback after all listeners have had a chance to update based on the state change + */ public default void onStatePostChange() { } + /** + * Required callback. Get the new state and do what you will with it. Keep in mind that + * other listeners are typically unordered and don't rely on your work being done before + * other peers + * + * Only called if the state is actually different + * @param newState the new {@link StatusBarState} + */ public void onStateChanged(int newState); - } - - private class RankedListener { - private final StateListener listener; - private final int rank; - private RankedListener(StateListener l, int r) { - listener = l; - rank = r; - } + /** + * Callback to be notified when Dozing changes. Dozing is stored separately from state. + * @param isDozing {@code true} if dozing according to {@link StatusBar} + */ + public default void onDozingChanged(boolean isDozing) {} } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java index d097c8e706ba..fbf12ed39561 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java @@ -50,7 +50,6 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.view.View; import android.widget.ImageView; -import android.widget.RemoteViews; import androidx.annotation.Nullable; @@ -102,11 +101,6 @@ public class NotificationData { public boolean autoRedacted; // whether the redacted notification was generated by us public int targetSdk; private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET; - public RemoteViews cachedContentView; - public RemoteViews cachedBigContentView; - public RemoteViews cachedHeadsUpContentView; - public RemoteViews cachedPublicContentView; - public RemoteViews cachedAmbientContentView; public CharSequence remoteInputText; public List<SnoozeCriterion> snoozeCriteria; public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL; @@ -178,14 +172,6 @@ public class NotificationData { } } - public View getExpandedContentView() { - return row.getPrivateLayout().getExpandedChild(); - } - - public View getPublicContentView() { - return row.getPublicLayout().getContractedChild(); - } - public void notifyFullScreenIntentLaunched() { setInterruption(); lastFullScreenIntentLaunchTime = SystemClock.elapsedRealtime(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index a3e982e77522..28d339aaeab2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -18,6 +18,10 @@ package com.android.systemui.statusbar.notification; import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; import static com.android.systemui.statusbar.NotificationRemoteInputManager .FORCE_REMOTE_INPUT_HISTORY; +import static com.android.systemui.statusbar.notification.row.NotificationInflater + .FLAG_CONTENT_VIEW_AMBIENT; +import static com.android.systemui.statusbar.notification.row.NotificationInflater + .FLAG_CONTENT_VIEW_HEADS_UP; import android.annotation.Nullable; import android.app.Notification; @@ -71,6 +75,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.NotificationUpdateHandler; import com.android.systemui.statusbar.notification.row.NotificationInflater; +import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag; import com.android.systemui.statusbar.notification.row.RowInflaterTask; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; @@ -440,25 +445,48 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. } private void addEntry(NotificationData.Entry shadeEntry) { - if (shouldHeadsUp(shadeEntry)) { - mHeadsUpManager.showNotification(shadeEntry); - // Mark as seen immediately - setNotificationShown(shadeEntry.notification); - } - if (shouldPulse(shadeEntry)) { - mAmbientPulseManager.showNotification(shadeEntry); - } addNotificationViews(shadeEntry); mCallback.onNotificationAdded(shadeEntry); } + /** + * Adds the entry to the respective alerting manager if the content view was inflated and + * the entry should still alert. + * + * @param entry entry to add + * @param inflatedFlags flags representing content views that were inflated + */ + private void showAlertingView(NotificationData.Entry entry, + @InflationFlag int inflatedFlags) { + if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) { + // Possible for shouldHeadsUp to change between the inflation starting and ending. + // If it does and we no longer need to heads up, we should free the view. + if (shouldHeadsUp(entry)) { + mHeadsUpManager.showNotification(entry); + // Mark as seen immediately + setNotificationShown(entry.notification); + } else { + entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP); + } + } + if ((inflatedFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) { + if (shouldPulse(entry)) { + mAmbientPulseManager.showNotification(entry); + } else { + entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT); + } + } + } + @Override - public void onAsyncInflationFinished(NotificationData.Entry entry) { + public void onAsyncInflationFinished(NotificationData.Entry entry, + @InflationFlag int inflatedFlags) { mPendingNotifications.remove(entry.key); // If there was an async task started after the removal, we don't want to add it back to // the list, otherwise we might get leaks. boolean isNew = mNotificationData.get(entry.key) == null; if (isNew && !entry.row.isRemoved()) { + showAlertingView(entry, inflatedFlags); addEntry(entry); } else if (!isNew && entry.row.hasLowPriorityStateUpdated()) { mVisualStabilityManager.onLowPriorityUpdated(entry); @@ -636,7 +664,11 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp); row.setSmartActions(entry.smartActions); - row.updateNotification(entry); + row.setEntry(entry); + + row.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP, shouldHeadsUp(entry)); + row.updateInflationFlag(FLAG_CONTENT_VIEW_AMBIENT, shouldPulse(entry)); + row.inflateViews(); } protected void addNotificationViews(NotificationData.Entry entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index bce613a33859..23492aa62e37 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -17,12 +17,19 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; +import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT; +import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; +import static com.android.systemui.statusbar.notification.row.NotificationInflater + .FLAG_CONTENT_VIEW_AMBIENT; +import static com.android.systemui.statusbar.notification.row.NotificationInflater + .FLAG_CONTENT_VIEW_HEADS_UP; import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationChannel; @@ -83,6 +90,7 @@ import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.logging.NotificationCounters; import com.android.systemui.statusbar.notification.NotificationUtils; +import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.phone.NotificationGroupManager; @@ -429,12 +437,59 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } } - public void updateNotification(NotificationData.Entry entry) { + /** + * Set the entry for the row. + * + * @param entry the entry this row is tied to + */ + public void setEntry(@NonNull NotificationData.Entry entry) { mEntry = entry; mStatusBarNotification = entry.notification; + cacheIsSystemNotification(); + } + + /** + * Inflate views based off the inflation flags set. Inflation happens asynchronously. + */ + public void inflateViews() { mNotificationInflater.inflateNotificationViews(); + } - cacheIsSystemNotification(); + /** + * Marks a content view as freeable, setting it so that future inflations do not reinflate + * and ensuring that the view is freed when it is safe to remove. + * + * @param inflationFlag flag corresponding to the content view to be freed + */ + public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) { + // View should not be reinflated in the future + updateInflationFlag(inflationFlag, false); + Runnable freeViewRunnable = () -> + mNotificationInflater.freeNotificationView(inflationFlag); + switch (inflationFlag) { + case FLAG_CONTENT_VIEW_HEADS_UP: + getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_HEADSUP, + freeViewRunnable); + break; + case FLAG_CONTENT_VIEW_AMBIENT: + getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_AMBIENT, + freeViewRunnable); + getPublicLayout().performWhenContentInactive(VISIBLE_TYPE_AMBIENT, + freeViewRunnable); + break; + default: + break; + } + } + + /** + * Update whether or not a content view should be inflated. + * + * @param flag the flag corresponding to the content view + * @param shouldInflate true if it should be inflated, false if it should not + */ + public void updateInflationFlag(@InflationFlag int flag, boolean shouldInflate) { + mNotificationInflater.updateInflationFlag(flag, shouldInflate); } /** @@ -581,7 +636,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView headsUpHeight = mMaxHeadsUpHeight; } NotificationViewWrapper headsUpWrapper = layout.getVisibleWrapper( - NotificationContentView.VISIBLE_TYPE_HEADSUP); + VISIBLE_TYPE_HEADSUP); if (headsUpWrapper != null) { headsUpHeight = Math.max(headsUpHeight, headsUpWrapper.getMinLayoutHeight()); } @@ -2616,6 +2671,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return shouldShowPublic() ? mPublicLayout : mPrivateLayout; } + public View getExpandedContentView() { + return getPrivateLayout().getExpandedChild(); + } + public void setLegacy(boolean legacy) { for (NotificationContentView l : mLayouts) { l.setLegacy(legacy); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 4ef8dbb19318..78564515a2c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -23,6 +23,7 @@ import android.content.Context; import android.graphics.Rect; import android.os.Build; import android.service.notification.StatusBarNotification; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; @@ -108,6 +109,10 @@ public class NotificationContentView extends FrameLayout { private NotificationGroupManager mGroupManager; private RemoteInputController mRemoteInputController; private Runnable mExpandedVisibleListener; + /** + * List of listeners for when content views become inactive (i.e. not the showing view). + */ + private final ArrayMap<View, Runnable> mOnContentViewInactiveListeners = new ArrayMap<>(); private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener = new ViewTreeObserver.OnPreDrawListener() { @@ -517,6 +522,14 @@ public class NotificationContentView extends FrameLayout { removeView(mAmbientChild); } if (child == null) { + mAmbientChild = null; + mAmbientWrapper = null; + if (mVisibleType == VISIBLE_TYPE_AMBIENT) { + mVisibleType = VISIBLE_TYPE_CONTRACTED; + } + if (mTransformationStartVisibleType == VISIBLE_TYPE_AMBIENT) { + mTransformationStartVisibleType = UNDEFINED; + } return; } addView(child); @@ -1163,6 +1176,7 @@ public class NotificationContentView extends FrameLayout { public void onNotificationUpdated(NotificationData.Entry entry) { mStatusBarNotification = entry.notification; + mOnContentViewInactiveListeners.clear(); mBeforeN = entry.targetSdk < Build.VERSION_CODES.N; updateAllSingleLineViews(); if (mContractedChild != null) { @@ -1620,6 +1634,58 @@ public class NotificationContentView extends FrameLayout { fireExpandedVisibleListenerIfVisible(); } + /** + * Set a one-shot listener to run when a given content view becomes inactive. + * + * @param visibleType visible type corresponding to the content view to listen + * @param listener runnable to run once when the content view becomes inactive + */ + public void performWhenContentInactive(int visibleType, Runnable listener) { + View view = getViewForVisibleType(visibleType); + // View is already inactive + if (view == null || isContentViewInactive(visibleType)) { + listener.run(); + return; + } + mOnContentViewInactiveListeners.put(view, listener); + } + + /** + * Whether or not the content view is inactive. This means it should not be visible + * or the showing content as removing it would cause visual jank. + * + * @param visibleType visible type corresponding to the content view to be removed + * @return true if the content view is inactive, false otherwise + */ + public boolean isContentViewInactive(int visibleType) { + View view = getViewForVisibleType(visibleType); + return isContentViewInactive(view); + } + + /** + * Whether or not the content view is inactive. + * + * @param view view to see if its inactive + * @return true if the view is inactive, false o/w + */ + private boolean isContentViewInactive(View view) { + if (view == null) { + return true; + } + return view.getVisibility() != VISIBLE && getViewForVisibleType(mVisibleType) != view; + } + + @Override + protected void onChildVisibilityChanged(View child, int oldVisibility, int newVisibility) { + super.onChildVisibilityChanged(child, oldVisibility, newVisibility); + if (isContentViewInactive(child)) { + Runnable listener = mOnContentViewInactiveListeners.remove(child); + if (listener != null) { + listener.run(); + } + } + } + public void setIsLowPriority(boolean isLowPriority) { mIsLowPriority = isLowPriority; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java index aa4765a349b4..ea1892be1b1f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java @@ -16,12 +16,17 @@ package com.android.systemui.statusbar.notification.row; +import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT; +import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; + +import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.os.AsyncTask; import android.os.CancellationSignal; import android.service.notification.StatusBarNotification; +import android.util.ArrayMap; import android.util.Log; import android.view.View; import android.widget.RemoteViews; @@ -35,6 +40,8 @@ import com.android.systemui.statusbar.notification.NotificationData; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.util.Assert; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -52,14 +59,64 @@ import java.util.concurrent.atomic.AtomicInteger; public class NotificationInflater { public static final String TAG = "NotificationInflater"; - @VisibleForTesting - static final int FLAG_REINFLATE_ALL = ~0; - private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0; - @VisibleForTesting - static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1; - private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2; - private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3; - private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, + prefix = {"FLAG_CONTENT_VIEW_"}, + value = { + FLAG_CONTENT_VIEW_CONTRACTED, + FLAG_CONTENT_VIEW_EXPANDED, + FLAG_CONTENT_VIEW_HEADS_UP, + FLAG_CONTENT_VIEW_AMBIENT, + FLAG_CONTENT_VIEW_PUBLIC, + FLAG_CONTENT_VIEW_ALL}) + public @interface InflationFlag {} + /** + * The default, contracted view. Seen when the shade is pulled down and in the lock screen + * if there is no worry about content sensitivity. + */ + public static final int FLAG_CONTENT_VIEW_CONTRACTED = 1; + + /** + * The expanded view. Seen when the user expands a notification. + */ + public static final int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1; + + /** + * The heads up view. Seen when a high priority notification peeks in from the top. + */ + public static final int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2; + + /** + * The ambient view. Seen when a high priority notification is received and the phone + * is dozing. + */ + public static final int FLAG_CONTENT_VIEW_AMBIENT = 1 << 3; + + /** + * The public view. This is a version of the contracted view that hides sensitive + * information and is used on the lock screen if we determine that the notification's + * content should be hidden. + */ + public static final int FLAG_CONTENT_VIEW_PUBLIC = 1 << 4; + + public static final int FLAG_CONTENT_VIEW_ALL = ~0; + + /** + * Content views that must be inflated at all times. + */ + @InflationFlag + private static final int REQUIRED_INFLATION_FLAGS = + FLAG_CONTENT_VIEW_CONTRACTED + | FLAG_CONTENT_VIEW_EXPANDED + | FLAG_CONTENT_VIEW_PUBLIC; + + /** + * The set of content views to inflate. + */ + @InflationFlag + private int mInflationFlags = REQUIRED_INFLATION_FLAGS; + private static final InflationExecutor EXECUTOR = new InflationExecutor(); private final ExpandableNotificationRow mRow; @@ -71,6 +128,7 @@ public class NotificationInflater { private InflationCallback mCallback; private boolean mRedactAmbient; private List<Notification.Action> mSmartActions; + private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>(); public NotificationInflater(ExpandableNotificationRow row) { mRow = row; @@ -89,10 +147,10 @@ public class NotificationInflater { if (childInGroup != mIsChildInGroup) { mIsChildInGroup = childInGroup; if (mIsLowPriority) { - int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW; + int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; inflateNotificationViews(flags); } - } ; + } } public void setUsesIncreasedHeight(boolean usesIncreasedHeight) { @@ -117,38 +175,67 @@ public class NotificationInflater { if (mRow.getEntry() == null) { return; } - inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW); + inflateNotificationViews(FLAG_CONTENT_VIEW_AMBIENT); } } /** + * Set whether or not a particular content view is needed and whether or not it should be + * inflated. These flags will be used when we inflate or reinflate. + * + * @param flag the {@link InflationFlag} corresponding to the view that should/should not be + * inflated + * @param shouldInflate true if the view should be inflated, false otherwise + */ + public void updateInflationFlag(@InflationFlag int flag, boolean shouldInflate) { + if (shouldInflate) { + mInflationFlags |= flag; + } else if ((REQUIRED_INFLATION_FLAGS & flag) == 0) { + mInflationFlags &= ~flag; + } + } + + /** + * Add flags for which content views should be inflated in addition to those already set. + * + * @param flags a set of {@link InflationFlag} corresponding to content views that should be + * inflated + */ + public void addInflationFlags(@InflationFlag int flags) { + mInflationFlags |= flags; + } + + /** * Inflate all views of this notification on a background thread. This is asynchronous and will * notify the callback once it's finished. */ public void inflateNotificationViews() { - inflateNotificationViews(FLAG_REINFLATE_ALL); + inflateNotificationViews(mInflationFlags); } /** - * Reinflate all views for the specified flags on a background thread. This is asynchronous and - * will notify the callback once it's finished. + * Inflate all views for the specified flags on a background thread. This is asynchronous and + * will notify the callback once it's finished. If the content view is already inflated, this + * will reinflate it. * - * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL} - * to reinflate all of views. + * @param reInflateFlags flags which views should be inflated. Should be a subset of + * {@link NotificationInflater#mInflationFlags} as only those will be + * inflated/reinflated. */ - @VisibleForTesting - void inflateNotificationViews(int reInflateFlags) { + private void inflateNotificationViews(@InflationFlag int reInflateFlags) { if (mRow.isRemoved()) { // We don't want to reinflate anything for removed notifications. Otherwise views might // be readded to the stack, leading to leaks. This may happen with low-priority groups // where the removal of already removed children can lead to a reinflation. return; } + // Only inflate the ones that are set. + reInflateFlags |= mInflationFlags; StatusBarNotification sbn = mRow.getEntry().notification; - AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mRow, - mIsLowPriority, - mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, - mCallback, mRemoteViewClickHandler, mSmartActions); + AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mCachedContentViews, + mRow, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, + mUsesIncreasedHeadsUpHeight, mRedactAmbient, mCallback, mRemoteViewClickHandler, + mSmartActions); if (mCallback != null && mCallback.doInflateSynchronous()) { task.onPostExecute(task.doInBackground()); } else { @@ -157,38 +244,80 @@ public class NotificationInflater { } @VisibleForTesting - InflationProgress inflateNotificationViews(int reInflateFlags, + InflationProgress inflateNotificationViews(@InflationFlag int reInflateFlags, Notification.Builder builder, Context packageContext) { InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); - apply(result, reInflateFlags, mRow, mRedactAmbient, mRemoteViewClickHandler, null); + apply(result, reInflateFlags, mCachedContentViews, mRow, mRedactAmbient, + mRemoteViewClickHandler, null); return result; } - private static InflationProgress createRemoteViews(int reInflateFlags, + /** + * Frees the content view associated with the inflation flag. Will only succeed if the + * view is safe to remove. + * + * @param inflateFlag the flag corresponding to the content view which should be freed + */ + public void freeNotificationView(@InflationFlag int inflateFlag) { + if ((mInflationFlags & inflateFlag) != 0) { + // The view should still be inflated. + return; + } + switch (inflateFlag) { + case FLAG_CONTENT_VIEW_HEADS_UP: + if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) { + mRow.getPrivateLayout().setHeadsUpChild(null); + mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP); + } + break; + case FLAG_CONTENT_VIEW_AMBIENT: + boolean privateSafeToRemove = mRow.getPrivateLayout().isContentViewInactive( + VISIBLE_TYPE_AMBIENT); + boolean publicSafeToRemove = mRow.getPublicLayout().isContentViewInactive( + VISIBLE_TYPE_AMBIENT); + if (privateSafeToRemove) { + mRow.getPrivateLayout().setAmbientChild(null); + } + if (publicSafeToRemove) { + mRow.getPublicLayout().setAmbientChild(null); + } + if (privateSafeToRemove && publicSafeToRemove) { + mCachedContentViews.remove(FLAG_CONTENT_VIEW_AMBIENT); + } + break; + case FLAG_CONTENT_VIEW_CONTRACTED: + case FLAG_CONTENT_VIEW_EXPANDED: + case FLAG_CONTENT_VIEW_PUBLIC: + default: + break; + } + } + + private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags, Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient, Context packageContext) { InflationProgress result = new InflationProgress(); isLowPriority = isLowPriority && !isChildInGroup; - if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight); } - if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) { result.newExpandedView = createExpandedView(builder, isLowPriority); } - if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) { result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight); } - if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) { result.newPublicView = builder.makePublicContentView(); } - if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) { result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification() : builder.makeAmbientNotification(); } @@ -199,18 +328,20 @@ public class NotificationInflater { return result; } - public static CancellationSignal apply(InflationProgress result, int reInflateFlags, + public static CancellationSignal apply(InflationProgress result, + @InflationFlag int reInflateFlags, ArrayMap<Integer, RemoteViews> cachedContentViews, ExpandableNotificationRow row, boolean redactAmbient, RemoteViews.OnClickHandler remoteViewClickHandler, @Nullable InflationCallback callback) { - NotificationData.Entry entry = row.getEntry(); NotificationContentView privateLayout = row.getPrivateLayout(); NotificationContentView publicLayout = row.getPublicLayout(); final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>(); - int flag = FLAG_REINFLATE_CONTENT_VIEW; + int flag = FLAG_CONTENT_VIEW_CONTRACTED; if ((reInflateFlags & flag) != 0) { - boolean isNewView = !canReapplyRemoteView(result.newContentView, entry.cachedContentView); + boolean isNewView = + !canReapplyRemoteView(result.newContentView, + cachedContentViews.get(FLAG_CONTENT_VIEW_CONTRACTED)); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -222,18 +353,19 @@ public class NotificationInflater { return result.newContentView; } }; - applyRemoteView(result, reInflateFlags, flag, row, redactAmbient, - isNewView, remoteViewClickHandler, callback, entry, privateLayout, + applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row, redactAmbient, + isNewView, remoteViewClickHandler, callback, privateLayout, privateLayout.getContractedChild(), privateLayout.getVisibleWrapper( NotificationContentView.VISIBLE_TYPE_CONTRACTED), runningInflations, applyCallback); } - flag = FLAG_REINFLATE_EXPANDED_VIEW; + flag = FLAG_CONTENT_VIEW_EXPANDED; if ((reInflateFlags & flag) != 0) { if (result.newExpandedView != null) { - boolean isNewView = !canReapplyRemoteView(result.newExpandedView, - entry.cachedBigContentView); + boolean isNewView = + !canReapplyRemoteView(result.newExpandedView, + cachedContentViews.get(FLAG_CONTENT_VIEW_EXPANDED)); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -245,8 +377,8 @@ public class NotificationInflater { return result.newExpandedView; } }; - applyRemoteView(result, reInflateFlags, flag, row, - redactAmbient, isNewView, remoteViewClickHandler, callback, entry, + applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row, + redactAmbient, isNewView, remoteViewClickHandler, callback, privateLayout, privateLayout.getExpandedChild(), privateLayout.getVisibleWrapper( NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations, @@ -254,11 +386,12 @@ public class NotificationInflater { } } - flag = FLAG_REINFLATE_HEADS_UP_VIEW; + flag = FLAG_CONTENT_VIEW_HEADS_UP; if ((reInflateFlags & flag) != 0) { if (result.newHeadsUpView != null) { - boolean isNewView = !canReapplyRemoteView(result.newHeadsUpView, - entry.cachedHeadsUpContentView); + boolean isNewView = + !canReapplyRemoteView(result.newHeadsUpView, + cachedContentViews.get(FLAG_CONTENT_VIEW_HEADS_UP)); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -270,19 +403,20 @@ public class NotificationInflater { return result.newHeadsUpView; } }; - applyRemoteView(result, reInflateFlags, flag, row, - redactAmbient, isNewView, remoteViewClickHandler, callback, entry, + applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row, + redactAmbient, isNewView, remoteViewClickHandler, callback, privateLayout, privateLayout.getHeadsUpChild(), privateLayout.getVisibleWrapper( - NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations, + VISIBLE_TYPE_HEADSUP), runningInflations, applyCallback); } } - flag = FLAG_REINFLATE_PUBLIC_VIEW; + flag = FLAG_CONTENT_VIEW_PUBLIC; if ((reInflateFlags & flag) != 0) { - boolean isNewView = !canReapplyRemoteView(result.newPublicView, - entry.cachedPublicContentView); + boolean isNewView = + !canReapplyRemoteView(result.newPublicView, + cachedContentViews.get(FLAG_CONTENT_VIEW_PUBLIC)); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -294,18 +428,19 @@ public class NotificationInflater { return result.newPublicView; } }; - applyRemoteView(result, reInflateFlags, flag, row, - redactAmbient, isNewView, remoteViewClickHandler, callback, entry, + applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row, + redactAmbient, isNewView, remoteViewClickHandler, callback, publicLayout, publicLayout.getContractedChild(), publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED), runningInflations, applyCallback); } - flag = FLAG_REINFLATE_AMBIENT_VIEW; + flag = FLAG_CONTENT_VIEW_AMBIENT; if ((reInflateFlags & flag) != 0) { NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout; - boolean isNewView = !canReapplyAmbient(row, redactAmbient) || - !canReapplyRemoteView(result.newAmbientView, entry.cachedAmbientContentView); + boolean isNewView = (!canReapplyAmbient(row, redactAmbient) + || !canReapplyRemoteView(result.newAmbientView, + cachedContentViews.get(FLAG_CONTENT_VIEW_AMBIENT))); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -317,15 +452,15 @@ public class NotificationInflater { return result.newAmbientView; } }; - applyRemoteView(result, reInflateFlags, flag, row, - redactAmbient, isNewView, remoteViewClickHandler, callback, entry, + applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row, + redactAmbient, isNewView, remoteViewClickHandler, callback, newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper( NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations, applyCallback); } // Let's try to finish, maybe nobody is even inflating anything - finishIfDone(result, reInflateFlags, runningInflations, callback, row, + finishIfDone(result, reInflateFlags, cachedContentViews, runningInflations, callback, row, redactAmbient); CancellationSignal cancellationSignal = new CancellationSignal(); cancellationSignal.setOnCancelListener( @@ -335,11 +470,11 @@ public class NotificationInflater { @VisibleForTesting static void applyRemoteView(final InflationProgress result, - final int reInflateFlags, int inflationId, - final ExpandableNotificationRow row, - final boolean redactAmbient, boolean isNewView, + final @InflationFlag int reInflateFlags, @InflationFlag int inflationId, + final ArrayMap<Integer, RemoteViews> cachedContentViews, + final ExpandableNotificationRow row, final boolean redactAmbient, boolean isNewView, RemoteViews.OnClickHandler remoteViewClickHandler, - @Nullable final InflationCallback callback, NotificationData.Entry entry, + @Nullable final InflationCallback callback, NotificationContentView parentLayout, View existingView, NotificationViewWrapper existingWrapper, final HashMap<Integer, CancellationSignal> runningInflations, @@ -362,7 +497,7 @@ public class NotificationInflater { existingWrapper.onReinflated(); } } catch (Exception e) { - handleInflationError(runningInflations, e, entry.notification, callback); + handleInflationError(runningInflations, e, row.getStatusBarNotification(), callback); // Add a running inflation to make sure we don't trigger callbacks. // Safe to do because only happens in tests. runningInflations.put(inflationId, new CancellationSignal()); @@ -381,8 +516,8 @@ public class NotificationInflater { existingWrapper.onReinflated(); } runningInflations.remove(inflationId); - finishIfDone(result, reInflateFlags, runningInflations, callback, row, - redactAmbient); + finishIfDone(result, reInflateFlags, cachedContentViews, runningInflations, + callback, row, redactAmbient); } @Override @@ -407,7 +542,8 @@ public class NotificationInflater { onViewApplied(newView); } catch (Exception anotherException) { runningInflations.remove(inflationId); - handleInflationError(runningInflations, e, entry.notification, callback); + handleInflationError(runningInflations, e, row.getStatusBarNotification(), + callback); } } }; @@ -430,8 +566,9 @@ public class NotificationInflater { runningInflations.put(inflationId, cancellationSignal); } - private static void handleInflationError(HashMap<Integer, CancellationSignal> runningInflations, - Exception e, StatusBarNotification notification, @Nullable InflationCallback callback) { + private static void handleInflationError( + HashMap<Integer, CancellationSignal> runningInflations, Exception e, + StatusBarNotification notification, @Nullable InflationCallback callback) { Assert.isMainThread(); runningInflations.values().forEach(CancellationSignal::cancel); if (callback != null) { @@ -444,7 +581,8 @@ public class NotificationInflater { * * @return true if the inflation was finished */ - private static boolean finishIfDone(InflationProgress result, int reInflateFlags, + private static boolean finishIfDone(InflationProgress result, + @InflationFlag int reInflateFlags, ArrayMap<Integer, RemoteViews> cachedContentViews, HashMap<Integer, CancellationSignal> runningInflations, @Nullable InflationCallback endListener, ExpandableNotificationRow row, boolean redactAmbient) { @@ -453,40 +591,40 @@ public class NotificationInflater { NotificationContentView privateLayout = row.getPrivateLayout(); NotificationContentView publicLayout = row.getPublicLayout(); if (runningInflations.isEmpty()) { - if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { if (result.inflatedContentView != null) { privateLayout.setContractedChild(result.inflatedContentView); } - entry.cachedContentView = result.newContentView; + cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView); } - if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) { if (result.inflatedExpandedView != null) { privateLayout.setExpandedChild(result.inflatedExpandedView); } else if (result.newExpandedView == null) { privateLayout.setExpandedChild(null); } - entry.cachedBigContentView = result.newExpandedView; + cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); row.setExpandable(result.newExpandedView != null); } - if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) { if (result.inflatedHeadsUpView != null) { privateLayout.setHeadsUpChild(result.inflatedHeadsUpView); } else if (result.newHeadsUpView == null) { privateLayout.setHeadsUpChild(null); } - entry.cachedHeadsUpContentView = result.newHeadsUpView; + cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); } - if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) { if (result.inflatedPublicView != null) { publicLayout.setContractedChild(result.inflatedPublicView); } - entry.cachedPublicContentView = result.newPublicView; + cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView); } - if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) { + if ((reInflateFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) { if (result.inflatedAmbientView != null) { NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout; @@ -495,12 +633,12 @@ public class NotificationInflater { newParent.setAmbientChild(result.inflatedAmbientView); otherParent.setAmbientChild(null); } - entry.cachedAmbientContentView = result.newAmbientView; + cachedContentViews.put(FLAG_CONTENT_VIEW_AMBIENT, result.newAmbientView); } entry.headsUpStatusBarText = result.headsUpStatusBarText; entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic; if (endListener != null) { - endListener.onAsyncInflationFinished(row.getEntry()); + endListener.onAsyncInflationFinished(row.getEntry(), reInflateFlags); } return true; } @@ -552,7 +690,15 @@ public class NotificationInflater { public interface InflationCallback { void handleInflationException(StatusBarNotification notification, Exception e); - void onAsyncInflationFinished(NotificationData.Entry entry); + + /** + * Callback for after the content views finish inflating. + * + * @param entry the entry with the content views set + * @param inflatedFlags the flags associated with the content views that were inflated + */ + void onAsyncInflationFinished(NotificationData.Entry entry, + @InflationFlag int inflatedFlags); /** * Used to disable async-ness for tests. Should only be used for tests. @@ -563,18 +709,13 @@ public class NotificationInflater { } public void clearCachesAndReInflate() { - NotificationData.Entry entry = mRow.getEntry(); - entry.cachedAmbientContentView = null; - entry.cachedBigContentView = null; - entry.cachedContentView = null; - entry.cachedHeadsUpContentView = null; - entry.cachedPublicContentView = null; + mCachedContentViews.clear(); inflateNotificationViews(); } private static boolean canReapplyAmbient(ExpandableNotificationRow row, boolean redactAmbient) { NotificationContentView ambientView = redactAmbient ? row.getPublicLayout() - : row.getPrivateLayout(); ; + : row.getPrivateLayout(); return ambientView.getAmbientChild() != null; } @@ -589,7 +730,8 @@ public class NotificationInflater { private final InflationCallback mCallback; private final boolean mUsesIncreasedHeadsUpHeight; private final boolean mRedactAmbient; - private int mReInflateFlags; + private @InflationFlag int mReInflateFlags; + private final ArrayMap<Integer, RemoteViews> mCachedContentViews; private ExpandableNotificationRow mRow; private Exception mError; private RemoteViews.OnClickHandler mRemoteViewClickHandler; @@ -597,15 +739,16 @@ public class NotificationInflater { private List<Notification.Action> mSmartActions; private AsyncInflationTask(StatusBarNotification notification, - int reInflateFlags, ExpandableNotificationRow row, boolean isLowPriority, - boolean isChildInGroup, boolean usesIncreasedHeight, + @InflationFlag int reInflateFlags, + ArrayMap<Integer, RemoteViews> cachedContentViews, ExpandableNotificationRow row, + boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient, - InflationCallback callback, - RemoteViews.OnClickHandler remoteViewClickHandler, + InflationCallback callback, RemoteViews.OnClickHandler remoteViewClickHandler, List<Notification.Action> smartActions) { mRow = row; mSbn = notification; mReInflateFlags = reInflateFlags; + mCachedContentViews = cachedContentViews; mContext = mRow.getContext(); mIsLowPriority = isLowPriority; mIsChildInGroup = isChildInGroup; @@ -622,6 +765,7 @@ public class NotificationInflater { } @VisibleForTesting + @InflationFlag public int getReInflateFlags() { return mReInflateFlags; } @@ -642,10 +786,9 @@ public class NotificationInflater { packageContext); processor.processNotification(notification, recoveredBuilder); } - return createRemoteViews(mReInflateFlags, - recoveredBuilder, mIsLowPriority, mIsChildInGroup, - mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, - packageContext); + return createRemoteViews(mReInflateFlags, recoveredBuilder, mIsLowPriority, + mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, + mRedactAmbient, packageContext); } catch (Exception e) { mError = e; return null; @@ -655,8 +798,8 @@ public class NotificationInflater { @Override protected void onPostExecute(InflationProgress result) { if (mError == null) { - mCancellationSignal = apply(result, mReInflateFlags, mRow, mRedactAmbient, - mRemoteViewClickHandler, this); + mCancellationSignal = apply(result, mReInflateFlags, mCachedContentViews, mRow, + mRedactAmbient, mRemoteViewClickHandler, this); } else { handleError(mError); } @@ -706,10 +849,11 @@ public class NotificationInflater { } @Override - public void onAsyncInflationFinished(NotificationData.Entry entry) { + public void onAsyncInflationFinished(NotificationData.Entry entry, + @InflationFlag int inflatedFlags) { mRow.getEntry().onInflationTaskFinished(); mRow.onNotificationUpdated(); - mCallback.onAsyncInflationFinished(mRow.getEntry()); + mCallback.onAsyncInflationFinished(mRow.getEntry(), inflatedFlags); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 2ca7282041cc..f76284dd1ffc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.row.wrapper; import android.content.Context; +import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.view.NotificationHeaderView; @@ -76,8 +77,11 @@ public abstract class NotificationViewWrapper implements TransformableView { } Drawable background = mView.getBackground(); if (background instanceof ColorDrawable) { - mBackgroundColor = ((ColorDrawable) background).getColor(); - mView.setBackground(null); + int backgroundColor = ((ColorDrawable) background).getColor(); + if (backgroundColor != Color.TRANSPARENT) { + mBackgroundColor = backgroundColor; + mView.setBackground(new ColorDrawable(Color.TRANSPARENT)); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index ae1353dd220c..072343a8b101 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -560,7 +560,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL return; } mDarkAmount = darkAmount; - mIndicationArea.setAlpha(1f - darkAmount); + mIndicationController.setDarkAmount(darkAmount); mLockIcon.setDarkAmount(darkAmount); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index 6bccf31b04a6..99a2cdc9a545 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -236,7 +236,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { try { WindowManagerGlobal.getWindowManagerService() - .watchRotation(mRotationWatcher, getContext().getDisplay().getDisplayId()); + .watchRotation(mRotationWatcher, getContext().getDisplayId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index c4efa9431317..980ba8751df4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -1100,10 +1100,11 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav visibilityToString(getCurrentView().getVisibility()), getCurrentView().getAlpha())); - pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s", + pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s darkIntensity=%.2f", mDisabledFlags, mVertical ? "true" : "false", - getMenuButton().isVisible() ? "true" : "false")); + getMenuButton().isVisible() ? "true" : "false", + getLightTransitionsController().getCurrentDarkIntensity())); dumpButton(pw, "back", getBackButton()); dumpButton(pw, "home", getHomeButton()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 56bef2e8ea59..3bdd60130de3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3756,9 +3756,6 @@ public class StatusBar extends SystemUI implements DemoMode, Trace.beginSection("StatusBar#updateKeyguardState"); if (mState == StatusBarState.KEYGUARD) { mKeyguardIndicationController.setVisible(true); - boolean dozingAnimated = mDozingRequested - && DozeParameters.getInstance(mContext).shouldControlScreenOff(); - mNotificationPanel.resetViews(dozingAnimated); if (mKeyguardUserSwitcher != null) { mKeyguardUserSwitcher.setKeyguard(true, mStatusBarStateController.fromShadeLocked()); @@ -3790,6 +3787,47 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override + public void onDozingChanged(boolean isDozing) { + Trace.beginSection("StatusBar#updateDozing"); + mDozing = isDozing; + + // Collapse the notification panel if open + boolean dozingAnimated = mDozingRequested + && DozeParameters.getInstance(mContext).shouldControlScreenOff(); + mNotificationPanel.resetViews(dozingAnimated); + + mKeyguardViewMediator.setAodShowing(mDozing); + + //TODO: make these folks listeners of StatusBarStateController.onDozingChanged + mStatusBarWindowController.setDozing(mDozing); + mStatusBarKeyguardViewManager.setDozing(mDozing); + if (mAmbientIndicationContainer instanceof DozeReceiver) { + ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing); + } + + mEntryManager.updateNotifications(); + updateDozingState(); + updateScrimController(); + updateReportRejectedTouchVisibility(); + Trace.endSection(); + } + + private void updateDozing() { + // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. + boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD + || mBiometricUnlockController.getMode() + == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; + // When in wake-and-unlock we may not have received a change to mState + // but we still should not be dozing, manually set to false. + if (mBiometricUnlockController.getMode() == + BiometricUnlockController.MODE_WAKE_AND_UNLOCK) { + dozing = false; + } + + mStatusBarStateController.setIsDozing(dozing); + } + + @Override public void onActivationReset(ActivatableNotificationView view) { if (view == mNotificationPanel.getActivatedChild()) { mNotificationPanel.setActivatedChild(null); @@ -4341,34 +4379,6 @@ public class StatusBar extends SystemUI implements DemoMode, updateScrimController(); } - private void updateDozing() { - Trace.beginSection("StatusBar#updateDozing"); - // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. - boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD - || mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; - // When in wake-and-unlock we may not have received a change to mState - // but we still should not be dozing, manually set to false. - if (mBiometricUnlockController.getMode() == - mBiometricUnlockController.MODE_WAKE_AND_UNLOCK) { - dozing = false; - } - if (mDozing != dozing) { - mDozing = dozing; - mKeyguardViewMediator.setAodShowing(mDozing); - mStatusBarWindowController.setDozing(mDozing); - mStatusBarKeyguardViewManager.setDozing(mDozing); - if (mAmbientIndicationContainer instanceof DozeReceiver) { - ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing); - } - mEntryManager.updateNotifications(); - updateDozingState(); - updateScrimController(); - updateReportRejectedTouchVisibility(); - } - Trace.endSection(); - } - @VisibleForTesting void updateScrimController() { Trace.beginSection("StatusBar#updateScrimController"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java index 57c7e285e29f..0d37b550d4e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -173,9 +173,9 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat } if (state.dozing) { - mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; } else { - mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index d477587f8ecb..b4d24d16113e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.policy; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -151,6 +153,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { for (OnHeadsUpChangedListener listener : mListeners) { listener.onHeadsUpStateChanged(entry, false); } + entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP); } protected void updatePinnedMode() { diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java index 66d5ee1a276f..4102e63f7330 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java @@ -54,7 +54,7 @@ public class UsbDebuggingActivity extends AlertActivity @Override public void onCreate(Bundle icicle) { Window window = getWindow(); - window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + window.addSystemFlags(WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); super.onCreate(icicle); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 4810b0b91c10..7abac0054e5d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -556,14 +556,15 @@ public class VolumeDialogImpl implements VolumeDialog { mHandler.removeMessages(H.SHOW); mHandler.removeMessages(H.DISMISS); rescheduleTimeoutH(); - mShowing = true; if (mConfigChanged) { - initDialog(); + initDialog(); // resets mShowing to false mConfigurableTexts.update(); mConfigChanged = false; } + initSettingsH(); + mShowing = true; mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); mController.notifyVisible(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index bdd05c7e6384..aae6d93cebed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -28,6 +30,7 @@ import android.app.Instrumentation; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; import android.content.Context; +import android.graphics.Color; import android.hardware.fingerprint.FingerprintManager; import android.os.Looper; import android.support.test.InstrumentationRegistry; @@ -45,6 +48,8 @@ import com.android.systemui.util.wakelock.WakeLockFake; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidJUnit4.class) @@ -54,9 +59,13 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { private String mDisclosureWithOrganization; - private DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); - private ViewGroup mIndicationArea = mock(ViewGroup.class); - private KeyguardIndicationTextView mDisclosure = mock(KeyguardIndicationTextView.class); + @Mock + private DevicePolicyManager mDevicePolicyManager; + @Mock + private ViewGroup mIndicationArea; + @Mock + private KeyguardIndicationTextView mDisclosure; + private KeyguardIndicationTextView mTextView; private KeyguardIndicationController mController; private WakeLockFake mWakeLock; @@ -64,7 +73,9 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); mInstrumentation = InstrumentationRegistry.getInstrumentation(); + mTextView = new KeyguardIndicationTextView(mContext); mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class)); @@ -74,6 +85,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { when(mIndicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure)) .thenReturn(mDisclosure); + when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView); mWakeLock = new WakeLockFake(); } @@ -189,4 +201,17 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { }); assertFalse("WakeLock expected: RELEASED, was: HELD", held[0]); } + + @Test + public void transientIndication_visibleWhenDozing() { + createController(); + + mController.setVisible(true); + mController.showTransientIndication("Test"); + mController.setDozing(true); + + assertThat(mTextView.getText()).isEqualTo("Test"); + assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE); + assertThat(mTextView.getAlpha()).isEqualTo(1f); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index edf29ac1c4f8..aca1f90b5aa8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -31,9 +31,9 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.widget.RemoteViews; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.notification.NotificationData; +import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag; import com.android.systemui.statusbar.notification.row.NotificationInflaterTest; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; @@ -67,16 +67,50 @@ public class NotificationTestHelper { mGroupManager.setHeadsUpManager(mHeadsUpManager); } + /** + * Creates a generic row. + * + * @return a generic row with no special properties. + * @throws Exception + */ public ExpandableNotificationRow createRow() throws Exception { return createRow(PKG, UID); } + /** + * Create a row with the package and user id specified. + * + * @param pkg package + * @param uid user id + * @return a row with a notification using the package and user id + * @throws Exception + */ public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception { return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */); } + /** + * Creates a row based off the notification given. + * + * @param notification the notification + * @return a row built off the notification + * @throws Exception + */ public ExpandableNotificationRow createRow(Notification notification) throws Exception { - return generateRow(notification, PKG, UID, false /* isGroupRow */); + return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */); + } + + /** + * Create a row with the specified content views inflated in addition to the default. + * + * @param extraInflationFlags the flags corresponding to the additional content views that + * should be inflated + * @return a row with the specified content views inflated in addition to the default + * @throws Exception + */ + public ExpandableNotificationRow createRow(@InflationFlag int extraInflationFlags) + throws Exception { + return generateRow(createNotification(), PKG, UID, extraInflationFlags); } /** @@ -122,34 +156,53 @@ public class NotificationTestHelper { boolean isGroupSummary, @Nullable String groupKey) throws Exception { + Notification notif = createNotification(isGroupSummary, groupKey); + return generateRow(notif, pkg, uid, 0 /* inflationFlags */); + } + + /** + * Creates a generic notification. + * + * @return a notification with no special properties + */ + private Notification createNotification() { + return createNotification(false /* isGroupSummary */, null /* groupKey */); + } + + /** + * Creates a notification with the given parameters. + * + * @param isGroupSummary whether the notification is a group summary + * @param groupKey the group key for the notification group used across notifications + * @return a notification that is in the group specified or standalone if unspecified + */ + private Notification createNotification(boolean isGroupSummary, + @Nullable String groupKey) { Notification publicVersion = new Notification.Builder(mContext).setSmallIcon( R.drawable.ic_person) .setCustomContentView(new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark)) .build(); - Notification.Builder notificationBuilder = - new Notification.Builder(mContext, "channelId") - .setSmallIcon(R.drawable.ic_person) - .setContentTitle("Title") - .setContentText("Text") - .setPublicVersion(publicVersion); - - // Group notification setup + Notification.Builder notificationBuilder = new Notification.Builder(mContext, "channelId") + .setSmallIcon(R.drawable.ic_person) + .setContentTitle("Title") + .setContentText("Text") + .setPublicVersion(publicVersion) + .setStyle(new Notification.BigTextStyle().bigText("Big Text")); if (isGroupSummary) { notificationBuilder.setGroupSummary(true); } if (!TextUtils.isEmpty(groupKey)) { notificationBuilder.setGroup(groupKey); } - - return generateRow(notificationBuilder.build(), pkg, uid, !TextUtils.isEmpty(groupKey)); + return notificationBuilder.build(); } private ExpandableNotificationRow generateRow( Notification notification, String pkg, int uid, - boolean isGroupRow) + @InflationFlag int extraInflationFlags) throws Exception { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( mContext.LAYOUT_INFLATER_SERVICE); @@ -179,8 +232,10 @@ public class NotificationTestHelper { entry.channel = new NotificationChannel( notification.getChannelId(), notification.getChannelId(), IMPORTANCE_DEFAULT); entry.channel.setBlockableSystem(true); + row.setEntry(entry); + row.getNotificationInflater().addInflationFlags(extraInflationFlags); NotificationInflaterTest.runThenWaitForInflation( - () -> row.updateNotification(entry), + () -> row.inflateViews(), row.getNotificationInflater()); // This would be done as part of onAsyncInflationFinished, but we skip large amounts of diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 4e16b7f94283..f01ae7a23533 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -68,6 +68,7 @@ import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.notification.row.NotificationInflater; import com.android.systemui.statusbar.notification.row.RowInflaterTask; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.NotificationGroupManager; @@ -134,8 +135,9 @@ public class NotificationEntryManagerTest extends SysuiTestCase { } @Override - public void onAsyncInflationFinished(NotificationData.Entry entry) { - super.onAsyncInflationFinished(entry); + public void onAsyncInflationFinished(NotificationData.Entry entry, + @NotificationInflater.InflationFlag int inflatedFlags) { + super.onAsyncInflationFinished(entry, inflatedFlags); mCountDownLatch.countDown(); } @@ -428,7 +430,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction()))); mEntryManager.updateNotificationRanking(mRankingMap); - verify(mRow).updateNotification(eq(mEntry)); + verify(mRow).setEntry(eq(mEntry)); assertEquals(1, mEntry.smartActions.size()); assertEquals("action", mEntry.smartActions.get(0).title); } @@ -443,7 +445,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { setSmartActions(mEntry.key, null); mEntryManager.updateNotificationRanking(mRankingMap); - verify(mRow, never()).updateNotification(eq(mEntry)); + verify(mRow, never()).setEntry(eq(mEntry)); assertEquals(0, mEntry.smartActions.size()); } @@ -457,7 +459,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction()))); mEntryManager.updateNotificationRanking(mRankingMap); - verify(mRow, never()).updateNotification(eq(mEntry)); + verify(mRow, never()).setEntry(eq(mEntry)); assertEquals(1, mEntry.smartActions.size()); assertEquals("action", mEntry.smartActions.get(0).title); } @@ -472,7 +474,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction()))); mEntryManager.updateNotificationRanking(mRankingMap); - verify(mRow, never()).updateNotification(eq(mEntry)); + verify(mRow, never()).setEntry(eq(mEntry)); assertEquals(1, mEntry.smartActions.size()); assertEquals("action", mEntry.smartActions.get(0).title); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 743b307d0666..cfc75261123a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -18,8 +18,13 @@ package com.android.systemui.statusbar.notification.row; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_ALL; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -35,6 +40,7 @@ import android.app.AppOpsManager; import android.app.NotificationChannel; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.ArraySet; import android.view.NotificationHeaderView; @@ -134,6 +140,15 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { } @Test + public void testFreeContentViewWhenSafe() throws Exception { + ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_CONTENT_VIEW_ALL); + + row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP); + + assertNull(row.getPrivateLayout().getHeadsUpChild()); + } + + @Test public void testAboveShelfChangedListenerCalled() throws Exception { ExpandableNotificationRow row = mNotificationTestHelper.createRow(); AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java index 81e79d1490b9..150d9337d4a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java @@ -16,10 +16,13 @@ package com.android.systemui.statusbar.notification.row; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_ALL; +import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_EXPANDED; -import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_REINFLATE_ALL; - -import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -34,6 +37,7 @@ import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; +import android.util.ArrayMap; import android.view.View; import android.view.ViewGroup; import android.widget.RemoteViews; @@ -82,7 +86,8 @@ public class NotificationInflaterTest extends SysuiTestCase { } @Override - public void onAsyncInflationFinished(NotificationData.Entry entry) { + public void onAsyncInflationFinished(NotificationData.Entry entry, + @NotificationInflater.InflationFlag int inflatedFlags) { } }); } @@ -91,7 +96,7 @@ public class NotificationInflaterTest extends SysuiTestCase { public void testIncreasedHeadsUpBeingUsed() { mNotificationInflater.setUsesIncreasedHeadsUpHeight(true); Notification.Builder builder = spy(mBuilder); - mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext); + mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, builder, mContext); verify(builder).createHeadsUpContentView(true); } @@ -99,7 +104,7 @@ public class NotificationInflaterTest extends SysuiTestCase { public void testIncreasedHeightBeingUsed() { mNotificationInflater.setUsesIncreasedHeight(true); Notification.Builder builder = spy(mBuilder); - mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext); + mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, builder, mContext); verify(builder).createContentView(true); } @@ -111,14 +116,14 @@ public class NotificationInflaterTest extends SysuiTestCase { } @Test - public void testInflationCallsOnlyRightMethod() throws Exception { - mRow.getPrivateLayout().removeAllViews(); - mRow.getEntry().cachedBigContentView = null; - runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews( - FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater); - assertTrue(mRow.getPrivateLayout().getChildCount() == 1); - assertTrue(mRow.getPrivateLayout().getChildAt(0) - == mRow.getPrivateLayout().getExpandedChild()); + public void testInflationOnlyInflatesSetFlags() throws Exception { + mNotificationInflater.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP, + true /* shouldInflate */); + runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), + mNotificationInflater); + + assertNotNull(mRow.getPrivateLayout().getHeadsUpChild()); + assertNull(mRow.getShowingLayout().getAmbientChild()); verify(mRow).onNotificationUpdated(); } @@ -155,8 +160,9 @@ public class NotificationInflaterTest extends SysuiTestCase { new NotificationInflater.InflationProgress(); result.packageContext = mContext; CountDownLatch countDownLatch = new CountDownLatch(1); - NotificationInflater.applyRemoteView(result, FLAG_REINFLATE_EXPANDED_VIEW, 0, mRow, - false /* redactAmbient */, true /* isNewView */, new RemoteViews.OnClickHandler(), + NotificationInflater.applyRemoteView(result, FLAG_CONTENT_VIEW_EXPANDED, 0, + new ArrayMap() /* cachedContentViews */, mRow, false /* redactAmbient */, + true /* isNewView */, new RemoteViews.OnClickHandler(), new NotificationInflater.InflationCallback() { @Override public void handleInflationException(StatusBarNotification notification, @@ -166,10 +172,11 @@ public class NotificationInflaterTest extends SysuiTestCase { } @Override - public void onAsyncInflationFinished(NotificationData.Entry entry) { + public void onAsyncInflationFinished(NotificationData.Entry entry, + @NotificationInflater.InflationFlag int inflatedFlags) { countDownLatch.countDown(); } - }, mRow.getEntry(), mRow.getPrivateLayout(), null, null, new HashMap<>(), + }, mRow.getPrivateLayout(), null, null, new HashMap<>(), new NotificationInflater.ApplyCallback() { @Override public void setResultView(View v) { @@ -186,16 +193,19 @@ public class NotificationInflaterTest extends SysuiTestCase { /* Cancelling requires us to be on the UI thread otherwise we might have a race */ @Test - public void testSupersedesExistingTask() throws Exception { + public void testSupersedesExistingTask() { + mNotificationInflater.addInflationFlags(FLAG_CONTENT_VIEW_ALL); mNotificationInflater.inflateNotificationViews(); + + // Trigger inflation of content and expanded only. mNotificationInflater.setIsLowPriority(true); mNotificationInflater.setIsChildInGroup(true); + InflationTask runningTask = mRow.getEntry().getRunningTask(); NotificationInflater.AsyncInflationTask asyncInflationTask = (NotificationInflater.AsyncInflationTask) runningTask; - Assert.assertSame("Successive inflations don't inherit the previous flags!", - asyncInflationTask.getReInflateFlags(), - NotificationInflater.FLAG_REINFLATE_ALL); + assertEquals("Successive inflations don't inherit the previous flags!", + asyncInflationTask.getReInflateFlags(), FLAG_CONTENT_VIEW_ALL); runningTask.abort(); } @@ -231,7 +241,8 @@ public class NotificationInflaterTest extends SysuiTestCase { } @Override - public void onAsyncInflationFinished(NotificationData.Entry entry) { + public void onAsyncInflationFinished(NotificationData.Entry entry, + @NotificationInflater.InflationFlag int inflatedFlags) { if (expectingException) { exceptionHolder.setException(new RuntimeException( "Inflation finished even though there should be an error")); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java index f7a7e0430977..de26c709922d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java @@ -74,14 +74,14 @@ public class StatusBarWindowControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(WindowManager.LayoutParams.class); verify(mWindowManager).updateViewLayout(any(), captor.capture()); int flag = captor.getValue().privateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; assertThat(flag).isNotEqualTo(0); reset(mWindowManager); mStatusBarWindowController.setDozing(false); verify(mWindowManager).updateViewLayout(any(), captor.capture()); flag = captor.getValue().privateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; assertThat(flag).isEqualTo(0); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index da52d408e125..39866a72ab98 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -56,6 +56,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.ShortcutServiceInternal; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.content.res.Resources; import android.content.res.TypedArray; @@ -629,10 +630,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku onClickIntent = mDevicePolicyManagerInternal.createShowAdminSupportIntent( providerUserId, true); } else { - final String dialogMessage = mPackageManagerInternal.getSuspendedDialogMessage( - providerPackage, providerUserId); + final SuspendDialogInfo dialogInfo = mPackageManagerInternal + .getSuspendedDialogInfo(providerPackage, providerUserId); onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent( - providerPackage, suspendingPackage, dialogMessage, providerUserId); + providerPackage, suspendingPackage, dialogInfo, providerUserId); } } else if (provider.maskedByQuietProfile) { showBadge = true; diff --git a/services/art-profile b/services/art-profile index 328f8f7a37a7..4168a3f4b28c 100644 --- a/services/art-profile +++ b/services/art-profile @@ -207,7 +207,7 @@ HPLandroid/hardware/weaver/V1_0/IWeaver;->read(ILjava/util/ArrayList;Landroid/ha HPLandroid/hardware/weaver/V1_0/IWeaver;->setHALInstrumentation()V HPLandroid/hardware/weaver/V1_0/IWeaver;->unlinkToDeath(Landroid/os/IHwBinder$DeathRecipient;)Z HPLandroid/hardware/weaver/V1_0/IWeaver;->write(ILjava/util/ArrayList;Ljava/util/ArrayList;)I -HPLandroid/media/IMediaExtractorUpdateService;->loadPlugins(Ljava/lang/String;)V +HPLandroid/media/IMediaUpdateService;->loadPlugins(Ljava/lang/String;)V HPLandroid/net/apf/ApfGenerator$Instruction;-><init>(Landroid/net/apf/ApfGenerator;Landroid/net/apf/ApfGenerator$Opcodes;Landroid/net/apf/ApfGenerator$Register;)V HPLandroid/net/apf/ApfGenerator$Instruction;->calculateImmSize(IZ)B HPLandroid/net/apf/ApfGenerator$Instruction;->calculateTargetLabelOffset()I @@ -3977,9 +3977,9 @@ PLandroid/hardware/weaver/V1_0/WeaverConfig;->readFromParcel(Landroid/os/HwParce PLandroid/hardware/weaver/V1_0/WeaverReadResponse;-><init>()V PLandroid/hardware/weaver/V1_0/WeaverReadResponse;->readEmbeddedFromParcel(Landroid/os/HwParcel;Landroid/os/HwBlob;J)V PLandroid/hardware/weaver/V1_0/WeaverReadResponse;->readFromParcel(Landroid/os/HwParcel;)V -PLandroid/media/IMediaExtractorUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V -PLandroid/media/IMediaExtractorUpdateService$Stub$Proxy;->loadPlugins(Ljava/lang/String;)V -PLandroid/media/IMediaExtractorUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaExtractorUpdateService; +PLandroid/media/IMediaUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V +PLandroid/media/IMediaUpdateService$Stub$Proxy;->loadPlugins(Ljava/lang/String;)V +PLandroid/media/IMediaUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaExtractorUpdateService; PLandroid/net/apf/-$$Lambda$ApfFilter$UV1wDVoVlbcxpr8zevj_aMFtUGw;-><init>()V PLandroid/net/apf/-$$Lambda$ApfFilter$UV1wDVoVlbcxpr8zevj_aMFtUGw;->applyAsInt(Ljava/lang/Object;)I PLandroid/net/apf/ApfCapabilities;-><init>(III)V diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 1b97926d39fb..eb31e782eb33 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -159,7 +159,7 @@ import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -public class BackupManagerService implements BackupManagerServiceInterface { +public class BackupManagerService { public static final String TAG = "BackupManagerService"; public static final boolean DEBUG = true; @@ -701,7 +701,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Utility: build a new random integer token. The low bits are the ordinal of the // operation for near-time uniqueness, and the upper bits are random for app- // side unpredictability. - @Override public int generateRandomIntegerToken() { int token = mTokenGenerator.nextInt(); if (token < 0) token = -token; @@ -1108,12 +1107,10 @@ public class BackupManagerService implements BackupManagerServiceInterface { return array; } - @Override public boolean setBackupPassword(String currentPw, String newPw) { return mBackupPasswordManager.setBackupPassword(currentPw, newPw); } - @Override public boolean hasBackupPassword() { return mBackupPasswordManager.hasBackupPassword(); } @@ -1590,7 +1587,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Get the restore-set token for the best-available restore set for this package: // the active set if possible, else the ancestral one. Returns zero if none available. - @Override public long getAvailableRestoreToken(String packageName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getAvailableRestoreToken"); @@ -1608,12 +1604,10 @@ public class BackupManagerService implements BackupManagerServiceInterface { return token; } - @Override public int requestBackup(String[] packages, IBackupObserver observer, int flags) { return requestBackup(packages, observer, null, flags); } - @Override public int requestBackup(String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup"); @@ -1702,7 +1696,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Cancel all running backups. - @Override public void cancelBackups() { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "cancelBackups"); if (MORE_DEBUG) { @@ -1732,7 +1725,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public void prepareOperationTimeout(int token, long interval, BackupRestoreTask callback, int operationType) { if (operationType != OP_TYPE_BACKUP_WAIT && operationType != OP_TYPE_RESTORE_WAIT) { @@ -1790,7 +1782,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // synchronous waiter case - @Override public boolean waitUntilOperationComplete(int token) { if (MORE_DEBUG) { Slog.i(TAG, "Blocking until operation complete for " @@ -1895,7 +1886,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } - @Override public void tearDownAgentAndKill(ApplicationInfo app) { if (app == null) { // Null means the system package, so just quietly move on. :) @@ -2049,7 +2039,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { * @return Whether ongoing work will continue. The return value here will be passed * along as the return value to the scheduled job's onStartJob() callback. */ - @Override public boolean beginFullBackup(FullBackupJob scheduledJob) { final long now = System.currentTimeMillis(); final long fullBackupInterval; @@ -2224,7 +2213,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // The job scheduler says our constraints don't hold any more, // so tear down any ongoing backup task right away. - @Override public void endFullBackup() { // offload the mRunningFullBackupTask.handleCancel() call to another thread, // as we might have to wait for mCancelLock @@ -2331,7 +2319,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // ----- IBackupManager binder interface ----- - @Override public void dataChanged(final String packageName) { final int callingUserHandle = UserHandle.getCallingUserId(); if (callingUserHandle != UserHandle.USER_SYSTEM) { @@ -2362,7 +2349,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Run an initialize operation for the given transport - @Override public void initializeTransports(String[] transportNames, IBackupObserver observer) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "initializeTransport"); @@ -2382,7 +2368,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Clear the given package's backup data from the current transport - @Override public void clearBackupData(String transportName, String packageName) { if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName + " on " + transportName); PackageInfo info; @@ -2438,7 +2423,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Run a backup pass immediately for any applications that have declared // that they have pending updates. - @Override public void backupNow() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow"); @@ -2480,7 +2464,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // // This is the variant used by 'adb backup'; it requires on-screen confirmation // by the user because it can be used to offload data over untrusted USB. - @Override public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem, boolean compress, boolean doKeyValue, String[] pkgList) { @@ -2558,7 +2541,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public void fullTransportBackup(String[] pkgNames) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullTransportBackup"); @@ -2618,7 +2600,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public void adbRestore(ParcelFileDescriptor fd) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore"); @@ -2719,7 +2700,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Confirm that the previously-requested full backup/restore operation can proceed. This // is used to require a user-facing disclosure about the operation. - @Override public void acknowledgeAdbBackupOrRestore(int token, boolean allow, String curPassword, String encPpassword, IFullBackupRestoreObserver observer) { if (DEBUG) { @@ -2819,7 +2799,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Enable/disable backups - @Override public void setBackupEnabled(boolean enable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setBackupEnabled"); @@ -2887,7 +2866,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Enable/disable automatic restore of app data at install time - @Override public void setAutoRestore(boolean doAutoRestore) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setAutoRestore"); @@ -2907,7 +2885,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Mark the backup service as having been provisioned - @Override public void setBackupProvisioned(boolean available) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setBackupProvisioned"); @@ -2917,7 +2894,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Report whether the backup mechanism is currently enabled - @Override public boolean isBackupEnabled() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "isBackupEnabled"); @@ -2925,7 +2901,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Report the name of the currently active transport - @Override public String getCurrentTransport() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getCurrentTransport"); @@ -2938,7 +2913,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { * Returns the {@link ComponentName} of the host service of the selected transport or {@code * null} if no transport selected or if the transport selected is not registered. */ - @Override @Nullable public ComponentName getCurrentTransportComponent() { mContext.enforceCallingOrSelfPermission( @@ -2954,7 +2928,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Report all known, available backup transports - @Override public String[] listAllTransports() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "listAllTransports"); @@ -2962,14 +2935,12 @@ public class BackupManagerService implements BackupManagerServiceInterface { return mTransportManager.getRegisteredTransportNames(); } - @Override public ComponentName[] listAllTransportComponents() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "listAllTransportComponents"); return mTransportManager.getRegisteredTransportComponents(); } - @Override public String[] getTransportWhitelist() { // No permission check, intentionally. Set<ComponentName> whitelistedComponents = mTransportManager.getTransportWhitelist(); @@ -3006,7 +2977,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { * @throws SecurityException If the UID of the calling process differs from the package UID of * {@code transportComponent} or if the caller does NOT have BACKUP permission. */ - @Override public void updateTransportAttributes( ComponentName transportComponent, String name, @@ -3070,7 +3040,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } /** Selects transport {@code transportName} and returns previous selected transport. */ - @Override @Deprecated @Nullable public String selectBackupTransport(String transportName) { @@ -3089,7 +3058,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public void selectBackupTransportAsync( ComponentName transportComponent, ISelectBackupTransportCallback listener) { mContext.enforceCallingOrSelfPermission( @@ -3161,7 +3129,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Supply the configuration Intent for the given transport. If the name is not one // of the available transports, or if the transport does not supply any configuration // UI, the method returns null. - @Override public Intent getConfigurationIntent(String transportName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getConfigurationIntent"); @@ -3186,7 +3153,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { * @param transportName The name of the registered transport. * @return The current destination string or null if the transport is not registered. */ - @Override public String getDestinationString(String transportName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BACKUP, "getDestinationString"); @@ -3204,7 +3170,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Supply the manage-data intent for the given transport. - @Override public Intent getDataManagementIntent(String transportName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getDataManagementIntent"); @@ -3223,7 +3188,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Supply the menu label for affordances that fire the manage-data intent // for the given transport. - @Override public String getDataManagementLabel(String transportName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getDataManagementLabel"); @@ -3242,7 +3206,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Callback: a requested backup agent has been instantiated. This should only // be called from the Activity Manager. - @Override public void agentConnected(String packageName, IBinder agentBinder) { synchronized (mAgentConnectLock) { if (Binder.getCallingUid() == Process.SYSTEM_UID) { @@ -3261,7 +3224,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Callback: a backup agent has failed to come up, or has unexpectedly quit. // If the agent failed to come up in the first place, the agentBinder argument // will be null. This should only be called from the Activity Manager. - @Override public void agentDisconnected(String packageName) { // TODO: handle backup being interrupted synchronized (mAgentConnectLock) { @@ -3278,7 +3240,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // An application being installed will need a restore pass, then the Package Manager // will need to be told when the restore is finished. - @Override public void restoreAtInstall(String packageName, int token) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid() @@ -3364,7 +3325,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } // Hand off a restore session - @Override public IRestoreSession beginRestoreSession(String packageName, String transport) { if (DEBUG) { Slog.v(TAG, "beginRestoreSession: pkg=" + packageName @@ -3430,7 +3390,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { // Note that a currently-active backup agent has notified us that it has // completed the given outstanding asynchronous backup/restore operation. - @Override public void opComplete(int token, long result) { if (MORE_DEBUG) { Slog.v(TAG, "opComplete: " + Integer.toHexString(token) + " result=" + result); @@ -3468,7 +3427,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public boolean isAppEligibleForBackup(String packageName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BACKUP, "isAppEligibleForBackup"); @@ -3490,7 +3448,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public String[] filterAppsEligibleForBackup(String[] packages) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BACKUP, "filterAppsEligibleForBackup"); @@ -3517,7 +3474,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; @@ -3667,7 +3623,6 @@ public class BackupManagerService implements BackupManagerServiceInterface { } - @Override public IBackupManager getBackupManagerBinder() { return mBackupManagerBinder; } diff --git a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java deleted file mode 100644 index a38a0e9918d2..000000000000 --- a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.backup; - -import android.annotation.Nullable; -import android.app.IBackupAgent; -import android.app.backup.IBackupManager; -import android.app.backup.IBackupManagerMonitor; -import android.app.backup.IBackupObserver; -import android.app.backup.IFullBackupRestoreObserver; -import android.app.backup.IRestoreSession; -import android.app.backup.ISelectBackupTransportCallback; -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Interface for BackupManagerService. - * - * Current and future implementations of BackupManagerService should use this interface, so that - * Trampoline is able to switch between them. - */ -public interface BackupManagerServiceInterface { - - void unlockSystemUser(); - - // Utility: build a new random integer token - int generateRandomIntegerToken(); - - boolean setBackupPassword(String currentPw, String newPw); - - boolean hasBackupPassword(); - - // Get the restore-set token for the best-available restore set for this package: - // the active set if possible, else the ancestral one. Returns zero if none available. - long getAvailableRestoreToken(String packageName); - - int requestBackup(String[] packages, IBackupObserver observer, int flags); - - int requestBackup(String[] packages, IBackupObserver observer, - IBackupManagerMonitor monitor, int flags); - - // Cancel all running backups. - void cancelBackups(); - - void prepareOperationTimeout(int token, long interval, BackupRestoreTask callback, - int operationType); - - // synchronous waiter case - boolean waitUntilOperationComplete(int token); - - void tearDownAgentAndKill(ApplicationInfo app); - - boolean beginFullBackup(FullBackupJob scheduledJob); - - // The job scheduler says our constraints don't hold any more, - // so tear down any ongoing backup task right away. - void endFullBackup(); - - void dataChanged(String packageName); - - // Initialize the given transport - void initializeTransports(String[] transportName, IBackupObserver observer); - - // Clear the given package's backup data from the current transport - void clearBackupData(String transportName, String packageName); - - // Run a backup pass immediately for any applications that have declared - // that they have pending updates. - void backupNow(); - - // Run a backup pass for the given packages, writing the resulting data stream - // to the supplied file descriptor. This method is synchronous and does not return - // to the caller until the backup has been completed. - // - // This is the variant used by 'adb backup'; it requires on-screen confirmation - // by the user because it can be used to offload data over untrusted USB. - void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, - boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem, - boolean compress, boolean doKeyValue, String[] pkgList); - - void fullTransportBackup(String[] pkgNames); - - void adbRestore(ParcelFileDescriptor fd); - - // Confirm that the previously-requested full backup/restore operation can proceed. This - // is used to require a user-facing disclosure about the operation. - void acknowledgeAdbBackupOrRestore(int token, boolean allow, - String curPassword, String encPpassword, IFullBackupRestoreObserver observer); - - // Enable/disable backups - void setBackupEnabled(boolean enable); - - // Enable/disable automatic restore of app data at install time - void setAutoRestore(boolean doAutoRestore); - - // Mark the backup service as having been provisioned - void setBackupProvisioned(boolean available); - - // Report whether the backup mechanism is currently enabled - boolean isBackupEnabled(); - - // Update the transport attributes - void updateTransportAttributes( - ComponentName transportComponent, - String name, - Intent configurationIntent, - String currentDestinationString, - Intent dataManagementIntent, - String dataManagementLabel); - - // Report the name of the currently active transport - String getCurrentTransport(); - - // Report the component name of the host service of the currently active transport - @Nullable - ComponentName getCurrentTransportComponent(); - - // Report all known, available backup transports - String[] listAllTransports(); - - ComponentName[] listAllTransportComponents(); - - String[] getTransportWhitelist(); - - // Select which transport to use for the next backup operation. - String selectBackupTransport(String transport); - - void selectBackupTransportAsync(ComponentName transport, - ISelectBackupTransportCallback listener); - - // Supply the configuration Intent for the given transport. If the name is not one - // of the available transports, or if the transport does not supply any configuration - // UI, the method returns null. - Intent getConfigurationIntent(String transportName); - - // Supply the configuration summary string for the given transport. If the name is - // not one of the available transports, or if the transport does not supply any - // summary / destination string, the method can return null. - // - // This string is used VERBATIM as the summary text of the relevant Settings item! - String getDestinationString(String transportName); - - // Supply the manage-data intent for the given transport. - Intent getDataManagementIntent(String transportName); - - // Supply the menu label for affordances that fire the manage-data intent - // for the given transport. - String getDataManagementLabel(String transportName); - - // Callback: a requested backup agent has been instantiated. This should only - // be called from the Activity Manager. - void agentConnected(String packageName, IBinder agentBinder); - - // Callback: a backup agent has failed to come up, or has unexpectedly quit. - // If the agent failed to come up in the first place, the agentBinder argument - // will be null. This should only be called from the Activity Manager. - void agentDisconnected(String packageName); - - // An application being installed will need a restore pass, then the Package Manager - // will need to be told when the restore is finished. - void restoreAtInstall(String packageName, int token); - - // Hand off a restore session - IRestoreSession beginRestoreSession(String packageName, String transport); - - // Note that a currently-active backup agent has notified us that it has - // completed the given outstanding asynchronous backup/restore operation. - void opComplete(int token, long result); - - boolean isAppEligibleForBackup(String packageName); - - String[] filterAppsEligibleForBackup(String[] packages); - - void dump(FileDescriptor fd, PrintWriter pw, String[] args); - - IBackupManager getBackupManagerBinder(); - - // Gets access to the backup/restore agent timeout parameters. - BackupAgentTimeoutParameters getAgentTimeoutParameters(); -} diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbRestoreEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbRestoreEngine.java index fbec5cb22af2..bb145769fc8c 100644 --- a/services/backup/java/com/android/server/backup/KeyValueAdbRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/KeyValueAdbRestoreEngine.java @@ -39,7 +39,7 @@ public class KeyValueAdbRestoreEngine implements Runnable { private static final String TAG = "KeyValueAdbRestoreEngine"; private static final boolean DEBUG = false; - private final BackupManagerServiceInterface mBackupManagerService; + private final BackupManagerService mBackupManagerService; private final File mDataDir; FileMetadata mInfo; @@ -48,7 +48,7 @@ public class KeyValueAdbRestoreEngine implements Runnable { IBackupAgent mAgent; int mToken; - public KeyValueAdbRestoreEngine(BackupManagerServiceInterface backupManagerService, + public KeyValueAdbRestoreEngine(BackupManagerService backupManagerService, File dataDir, FileMetadata info, ParcelFileDescriptor inFD, IBackupAgent agent, int token) { mBackupManagerService = backupManagerService; diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index 787d667afe51..818154b283da 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -76,7 +76,7 @@ public class Trampoline extends IBackupManager.Stub { final Context mContext; final File mSuppressFile; // existence testing & creating synchronized on 'this' final boolean mGlobalDisable; - volatile BackupManagerServiceInterface mService; + volatile BackupManagerService mService; private HandlerThread mHandlerThread; @@ -100,7 +100,7 @@ public class Trampoline extends IBackupManager.Stub { BACKUP_SUPPRESS_FILENAME); } - protected BackupManagerServiceInterface createBackupManagerService() { + protected BackupManagerService createBackupManagerService() { return BackupManagerService.create(mContext, this, mHandlerThread); } @@ -135,7 +135,7 @@ public class Trampoline extends IBackupManager.Stub { initialize(UserHandle.USER_SYSTEM); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; Slog.i(TAG, "Unlocking system user; mService=" + mService); if (svc != null) { svc.unlockSystemUser(); @@ -198,7 +198,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void dataChanged(String packageName) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.dataChanged(packageName); } @@ -207,7 +207,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void initializeTransports(String[] transportNames, IBackupObserver observer) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.initializeTransports(transportNames, observer); } @@ -216,7 +216,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void clearBackupData(String transportName, String packageName) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.clearBackupData(transportName, packageName); } @@ -224,7 +224,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void agentConnected(String packageName, IBinder agent) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.agentConnected(packageName, agent); } @@ -232,7 +232,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void agentDisconnected(String packageName) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.agentDisconnected(packageName); } @@ -240,7 +240,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void restoreAtInstall(String packageName, int token) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.restoreAtInstall(packageName, token); } @@ -248,7 +248,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void setBackupEnabled(boolean isEnabled) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.setBackupEnabled(isEnabled); } @@ -256,7 +256,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void setAutoRestore(boolean doAutoRestore) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.setAutoRestore(doAutoRestore); } @@ -264,7 +264,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void setBackupProvisioned(boolean isProvisioned) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.setBackupProvisioned(isProvisioned); } @@ -272,25 +272,25 @@ public class Trampoline extends IBackupManager.Stub { @Override public boolean isBackupEnabled() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.isBackupEnabled() : false; } @Override public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.setBackupPassword(currentPw, newPw) : false; } @Override public boolean hasBackupPassword() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.hasBackupPassword() : false; } @Override public void backupNow() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.backupNow(); } @@ -301,7 +301,7 @@ public class Trampoline extends IBackupManager.Stub { boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem, boolean doCompress, boolean doKeyValue, String[] packageNames) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.adbBackup(fd, includeApks, includeObbs, includeShared, doWidgets, allApps, allIncludesSystem, doCompress, doKeyValue, packageNames); @@ -310,7 +310,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void fullTransportBackup(String[] packageNames) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.fullTransportBackup(packageNames); } @@ -318,7 +318,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void adbRestore(ParcelFileDescriptor fd) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.adbRestore(fd); } @@ -328,7 +328,7 @@ public class Trampoline extends IBackupManager.Stub { public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, String encryptionPassword, IFullBackupRestoreObserver observer) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.acknowledgeAdbBackupOrRestore(token, allow, curPassword, encryptionPassword, observer); @@ -337,7 +337,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public String getCurrentTransport() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getCurrentTransport() : null; } @@ -348,25 +348,25 @@ public class Trampoline extends IBackupManager.Stub { @Override @Nullable public ComponentName getCurrentTransportComponent() { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getCurrentTransportComponent() : null; } @Override public String[] listAllTransports() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.listAllTransports() : null; } @Override public ComponentName[] listAllTransportComponents() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.listAllTransportComponents() : null; } @Override public String[] getTransportWhitelist() { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getTransportWhitelist() : null; } @@ -378,7 +378,7 @@ public class Trampoline extends IBackupManager.Stub { String currentDestinationString, @Nullable Intent dataManagementIntent, String dataManagementLabel) { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.updateTransportAttributes( transportComponent, @@ -392,14 +392,14 @@ public class Trampoline extends IBackupManager.Stub { @Override public String selectBackupTransport(String transport) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.selectBackupTransport(transport) : null; } @Override public void selectBackupTransportAsync(ComponentName transport, ISelectBackupTransportCallback listener) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.selectBackupTransportAsync(transport, listener); } else { @@ -415,38 +415,38 @@ public class Trampoline extends IBackupManager.Stub { @Override public Intent getConfigurationIntent(String transport) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getConfigurationIntent(transport) : null; } @Override public String getDestinationString(String transport) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getDestinationString(transport) : null; } @Override public Intent getDataManagementIntent(String transport) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getDataManagementIntent(transport) : null; } @Override public String getDataManagementLabel(String transport) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getDataManagementLabel(transport) : null; } @Override public IRestoreSession beginRestoreSession(String packageName, String transportID) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.beginRestoreSession(packageName, transportID) : null; } @Override public void opComplete(int token, long result) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.opComplete(token, result); } @@ -454,26 +454,26 @@ public class Trampoline extends IBackupManager.Stub { @Override public long getAvailableRestoreToken(String packageName) { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.getAvailableRestoreToken(packageName) : 0; } @Override public boolean isAppEligibleForBackup(String packageName) { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.isAppEligibleForBackup(packageName) : false; } @Override public String[] filterAppsEligibleForBackup(String[] packages) { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.filterAppsEligibleForBackup(packages) : null; } @Override public int requestBackup(String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags) throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc == null) { return BackupManager.ERROR_BACKUP_NOT_ALLOWED; } @@ -482,7 +482,7 @@ public class Trampoline extends IBackupManager.Stub { @Override public void cancelBackups() throws RemoteException { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.cancelBackups(); } @@ -492,7 +492,7 @@ public class Trampoline extends IBackupManager.Stub { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.dump(fd, pw, args); } else { @@ -503,12 +503,12 @@ public class Trampoline extends IBackupManager.Stub { // Full backup/restore entry points - non-Binder; called directly // by the full-backup scheduled job /* package */ boolean beginFullBackup(FullBackupJob scheduledJob) { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; return (svc != null) ? svc.beginFullBackup(scheduledJob) : false; } /* package */ void endFullBackup() { - BackupManagerServiceInterface svc = mService; + BackupManagerService svc = mService; if (svc != null) { svc.endFullBackup(); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index bc6254a76327..b750d7959167 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3495,7 +3495,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy(); if (!ProxyTracker.proxyInfoEqual(newProxyInfo, oldProxyInfo)) { - mProxyTracker.sendProxyBroadcast(mProxyTracker.getDefaultProxy()); + mProxyTracker.sendProxyBroadcast(); } } @@ -4782,15 +4782,14 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private String getNetworkPermission(NetworkCapabilities nc) { - // TODO: make these permission strings AIDL constants instead. + private int getNetworkPermission(NetworkCapabilities nc) { if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { - return NetworkManagementService.PERMISSION_SYSTEM; + return INetd.PERMISSION_SYSTEM; } if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) { - return NetworkManagementService.PERMISSION_NETWORK; + return INetd.PERMISSION_NETWORK; } - return null; + return INetd.PERMISSION_NONE; } /** @@ -4863,9 +4862,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (Objects.equals(nai.networkCapabilities, newNc)) return; - final String oldPermission = getNetworkPermission(nai.networkCapabilities); - final String newPermission = getNetworkPermission(newNc); - if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) { + final int oldPermission = getNetworkPermission(nai.networkCapabilities); + final int newPermission = getNetworkPermission(newNc); + if (oldPermission != newPermission && nai.created && !nai.isVPN()) { try { mNMS.setNetworkPermission(nai.network.netId, newPermission); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 26421a2acb66..0b30ff5cc398 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -242,11 +242,9 @@ public class DeviceIdleController extends SystemService private ActivityTaskManagerInternal mLocalActivityTaskManager; private PowerManagerInternal mLocalPowerManager; private PowerManager mPowerManager; - private ConnectivityService mConnectivityService; private INetworkPolicyManager mNetworkPolicyManager; private SensorManager mSensorManager; private Sensor mMotionSensor; - private LocationManager mLocationManager; private LocationRequest mLocationRequest; private Intent mIdleIntent; private Intent mLightIdleIntent; @@ -1508,6 +1506,8 @@ public class DeviceIdleController extends SystemService static class Injector { private final Context mContext; + private ConnectivityService mConnectivityService; + private LocationManager mLocationManager; Injector(Context ctx) { mContext = ctx; @@ -1527,7 +1527,11 @@ public class DeviceIdleController extends SystemService } ConnectivityService getConnectivityService() { - return (ConnectivityService) ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + if (mConnectivityService == null) { + mConnectivityService = (ConnectivityService) ServiceManager.getService( + Context.CONNECTIVITY_SERVICE); + } + return mConnectivityService; } Constants getConstants(DeviceIdleController controller, Handler handler, @@ -1536,7 +1540,10 @@ public class DeviceIdleController extends SystemService } LocationManager getLocationManager() { - return mContext.getSystemService(LocationManager.class); + if (mLocationManager == null) { + mLocationManager = mContext.getSystemService(LocationManager.class); + } + return mLocationManager; } MyHandler getHandler(DeviceIdleController controller) { @@ -1666,7 +1673,6 @@ public class DeviceIdleController extends SystemService mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "deviceidle_going_idle"); mGoingIdleWakeLock.setReferenceCounted(true); - mConnectivityService = mInjector.getConnectivityService(); mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); mNetworkPolicyManagerInternal = getLocalService(NetworkPolicyManagerInternal.class); @@ -1689,7 +1695,6 @@ public class DeviceIdleController extends SystemService if (getContext().getResources().getBoolean( com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { - mLocationManager = mInjector.getLocationManager(); mLocationRequest = new LocationRequest() .setQuality(LocationRequest.ACCURACY_FINE) .setInterval(0) @@ -2160,10 +2165,17 @@ public class DeviceIdleController extends SystemService } } + @VisibleForTesting + boolean isNetworkConnected() { + synchronized (this) { + return mNetworkConnected; + } + } + void updateConnectivityState(Intent connIntent) { ConnectivityService cm; synchronized (this) { - cm = mConnectivityService; + cm = mInjector.getConnectivityService(); } if (cm == null) { return; @@ -2276,13 +2288,17 @@ public class DeviceIdleController extends SystemService /** Must only be used in tests. */ @VisibleForTesting void setDeepEnabledForTest(boolean enabled) { - mDeepEnabled = enabled; + synchronized (this) { + mDeepEnabled = enabled; + } } /** Must only be used in tests. */ @VisibleForTesting void setLightEnabledForTest(boolean enabled) { - mLightEnabled = enabled; + synchronized (this) { + mLightEnabled = enabled; + } } void becomeInactiveIfAppropriateLocked() { @@ -2338,7 +2354,9 @@ public class DeviceIdleController extends SystemService */ @VisibleForTesting void setLightStateForTest(int lightState) { - mLightState = lightState; + synchronized (this) { + mLightState = lightState; + } } @VisibleForTesting @@ -2429,12 +2447,6 @@ public class DeviceIdleController extends SystemService } } - /** Must only be used in tests. */ - @VisibleForTesting - void setLocationManagerForTest(LocationManager lm) { - mLocationManager = lm; - } - @VisibleForTesting int getState() { return mState; @@ -2486,18 +2498,19 @@ public class DeviceIdleController extends SystemService if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); EventLogTags.writeDeviceIdle(mState, reason); scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false); - if (mLocationManager != null - && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { - mLocationManager.requestLocationUpdates(mLocationRequest, + LocationManager locationManager = mInjector.getLocationManager(); + if (locationManager != null + && locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { + locationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener, mHandler.getLooper()); mLocating = true; } else { mHasNetworkLocation = false; } - if (mLocationManager != null - && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { + if (locationManager != null + && locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { mHasGps = true; - mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, mGpsLocationListener, mHandler.getLooper()); mLocating = true; } else { @@ -2575,7 +2588,9 @@ public class DeviceIdleController extends SystemService /** Must only be used in tests. */ @VisibleForTesting void setActiveIdleOpsForTest(int count) { - mActiveIdleOpCount = count; + synchronized (this) { + mActiveIdleOpCount = count; + } } void setJobsActive(boolean active) { @@ -2751,8 +2766,9 @@ public class DeviceIdleController extends SystemService void cancelLocatingLocked() { if (mLocating) { - mLocationManager.removeUpdates(mGenericLocationListener); - mLocationManager.removeUpdates(mGpsLocationListener); + LocationManager locationManager = mInjector.getLocationManager(); + locationManager.removeUpdates(mGenericLocationListener); + locationManager.removeUpdates(mGpsLocationListener); mLocating = false; } } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index cf39e95fd735..f510d8355179 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -170,19 +170,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub */ public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; - /** - * String to pass to netd to indicate that a network is only accessible - * to apps that have the CHANGE_NETWORK_STATE permission. - */ - public static final String PERMISSION_NETWORK = "NETWORK"; - - /** - * String to pass to netd to indicate that a network is only - * accessible to system apps and those with the CONNECTIVITY_INTERNAL - * permission. - */ - public static final String PERMISSION_SYSTEM = "SYSTEM"; - static class NetdResponseCode { /* Keep in sync with system/netd/server/ResponseCode.h */ public static final int InterfaceListResult = 110; @@ -223,6 +210,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; + static final boolean MODIFY_OPERATION_ADD = true; + static final boolean MODIFY_OPERATION_REMOVE = false; + /** * Binder context for this service */ @@ -1122,41 +1112,47 @@ public class NetworkManagementService extends INetworkManagementService.Stub @Override public void addRoute(int netId, RouteInfo route) { - modifyRoute("add", "" + netId, route); + modifyRoute(MODIFY_OPERATION_ADD, netId, route); } @Override public void removeRoute(int netId, RouteInfo route) { - modifyRoute("remove", "" + netId, route); + modifyRoute(MODIFY_OPERATION_REMOVE, netId, route); } - private void modifyRoute(String action, String netId, RouteInfo route) { + private void modifyRoute(boolean add, int netId, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - final Command cmd = new Command("network", "route", action, netId); - - // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr - cmd.appendArg(route.getInterface()); - cmd.appendArg(route.getDestination().toString()); + final String ifName = route.getInterface(); + final String dst = route.getDestination().toString(); + final String nextHop; switch (route.getType()) { case RouteInfo.RTN_UNICAST: if (route.hasGateway()) { - cmd.appendArg(route.getGateway().getHostAddress()); + nextHop = route.getGateway().getHostAddress(); + } else { + nextHop = INetd.NEXTHOP_NONE; } break; case RouteInfo.RTN_UNREACHABLE: - cmd.appendArg("unreachable"); + nextHop = INetd.NEXTHOP_UNREACHABLE; break; case RouteInfo.RTN_THROW: - cmd.appendArg("throw"); + nextHop = INetd.NEXTHOP_THROW; + break; + default: + nextHop = INetd.NEXTHOP_NONE; break; } - try { - mConnector.execute(cmd); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + if (add) { + mNetdService.networkAddRoute(netId, ifName, dst, nextHop); + } else { + mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop); + } + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -1916,44 +1912,21 @@ public class NetworkManagementService extends INetworkManagementService.Stub @Override public void addVpnUidRanges(int netId, UidRange[] ranges) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; - argv[0] = "users"; - argv[1] = "add"; - argv[2] = netId; - int argc = 3; - // Avoid overly long commands by limiting number of UID ranges per command. - for (int i = 0; i < ranges.length; i++) { - argv[argc++] = ranges[i].toString(); - if (i == (ranges.length - 1) || argc == argv.length) { - try { - mConnector.execute("network", Arrays.copyOf(argv, argc)); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - argc = 3; - } + + try { + mNetdService.networkAddUidRanges(netId, ranges); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @Override public void removeVpnUidRanges(int netId, UidRange[] ranges) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; - argv[0] = "users"; - argv[1] = "remove"; - argv[2] = netId; - int argc = 3; - // Avoid overly long commands by limiting number of UID ranges per command. - for (int i = 0; i < ranges.length; i++) { - argv[argc++] = ranges[i].toString(); - if (i == (ranges.length - 1) || argc == argv.length) { - try { - mConnector.execute("network", Arrays.copyOf(argv, argc)); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - argc = 3; - } + try { + mNetdService.networkRemoveUidRanges(netId, ranges); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2412,17 +2385,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public void createPhysicalNetwork(int netId, String permission) { + public void createPhysicalNetwork(int netId, int permission) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - if (permission != null) { - mConnector.execute("network", "create", netId, permission); - } else { - mConnector.execute("network", "create", netId); - } - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkCreatePhysical(netId, permission); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2431,10 +2400,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0", - secure ? "1" : "0"); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkCreateVpn(netId, hasDNS, secure); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2455,20 +2423,24 @@ public class NetworkManagementService extends INetworkManagementService.Stub @Override public void addInterfaceToNetwork(String iface, int netId) { - modifyInterfaceInNetwork("add", "" + netId, iface); + modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface); } @Override public void removeInterfaceFromNetwork(String iface, int netId) { - modifyInterfaceInNetwork("remove", "" + netId, iface); + modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, netId, iface); } - private void modifyInterfaceInNetwork(String action, String netId, String iface) { + private void modifyInterfaceInNetwork(boolean add, int netId, String iface) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "interface", action, netId, iface); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + if (add) { + mNetdService.networkAddInterface(netId, iface); + } else { + mNetdService.networkRemoveInterface(netId, iface); + } + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2476,20 +2448,20 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - final Command cmd = new Command("network", "route", "legacy", uid, "add", netId); - - // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr final LinkAddress la = routeInfo.getDestinationLinkAddress(); - cmd.appendArg(routeInfo.getInterface()); - cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); + final String ifName = routeInfo.getInterface(); + final String dst = la.toString(); + final String nextHop; + if (routeInfo.hasGateway()) { - cmd.appendArg(routeInfo.getGateway().getHostAddress()); + nextHop = routeInfo.getGateway().getHostAddress(); + } else { + nextHop = ""; } - try { - mConnector.execute(cmd); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkAddLegacyRoute(netId, ifName, dst, nextHop, uid); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2498,9 +2470,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "default", "set", netId); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkSetDefault(netId); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2509,49 +2481,41 @@ public class NetworkManagementService extends INetworkManagementService.Stub mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "default", "clear"); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkClearDefault(); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @Override - public void setNetworkPermission(int netId, String permission) { + public void setNetworkPermission(int netId, int permission) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - if (permission != null) { - mConnector.execute("network", "permission", "network", "set", permission, netId); - } else { - mConnector.execute("network", "permission", "network", "clear", netId); - } - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkSetPermissionForNetwork(netId, permission); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } + private int parsePermission(String permission) { + if (permission.equals("NETWORK")) { + return INetd.PERMISSION_NETWORK; + } + if (permission.equals("SYSTEM")) { + return INetd.PERMISSION_SYSTEM; + } + return INetd.PERMISSION_NONE; + } @Override public void setPermission(String permission, int[] uids) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND]; - argv[0] = "permission"; - argv[1] = "user"; - argv[2] = "set"; - argv[3] = permission; - int argc = 4; - // Avoid overly long commands by limiting number of UIDs per command. - for (int i = 0; i < uids.length; ++i) { - argv[argc++] = uids[i]; - if (i == uids.length - 1 || argc == argv.length) { - try { - mConnector.execute("network", Arrays.copyOf(argv, argc)); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - argc = 4; - } + try { + mNetdService.networkSetPermissionForUser(parsePermission(permission), uids); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2559,22 +2523,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void clearPermission(int[] uids) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; - argv[0] = "permission"; - argv[1] = "user"; - argv[2] = "clear"; - int argc = 3; - // Avoid overly long commands by limiting number of UIDs per command. - for (int i = 0; i < uids.length; ++i) { - argv[argc++] = uids[i]; - if (i == uids.length - 1 || argc == argv.length) { - try { - mConnector.execute("network", Arrays.copyOf(argv, argc)); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - argc = 3; - } + try { + mNetdService.networkClearPermissionForUser(uids); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2583,9 +2535,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "protect", "allow", uid); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkSetProtectAllow(uid); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @@ -2594,26 +2546,26 @@ public class NetworkManagementService extends INetworkManagementService.Stub mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "protect", "deny", uid); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkSetProtectDeny(uid); + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); } } @Override public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { - modifyInterfaceInNetwork("add", "local", iface); + modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.NETID_LOCAL, iface); for (RouteInfo route : routes) { if (!route.isDefaultRoute()) { - modifyRoute("add", "local", route); + modifyRoute(MODIFY_OPERATION_ADD, INetd.NETID_LOCAL, route); } } } @Override public void removeInterfaceFromLocalNetwork(String iface) { - modifyInterfaceInNetwork("remove", "local", iface); + modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.NETID_LOCAL, iface); } @Override @@ -2622,7 +2574,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub for (RouteInfo route : routes) { try { - modifyRoute("remove", "local", route); + modifyRoute(MODIFY_OPERATION_REMOVE, INetd.NETID_LOCAL, route); } catch (IllegalStateException e) { failures++; } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 8e64b5063302..f4ec1f9d5b27 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -25,7 +25,6 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -552,7 +551,7 @@ public final class ActiveServices { if (!callerFg && !fgRequired && r.app == null && mAm.mUserController.hasStartedUserState(r.userId)) { ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); - if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { + if (proc == null || proc.getCurProcState() > ActivityManager.PROCESS_STATE_RECEIVER) { // If this is not coming from a foreground caller, then we may want // to delay the start if there are already other background services // that are starting. This is to avoid process start spam when lots @@ -580,7 +579,7 @@ public final class ActiveServices { } if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r); addToStarting = true; - } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { + } else if (proc.getCurProcState() >= ActivityManager.PROCESS_STATE_SERVICE) { // We slightly loosen when we will enqueue this new service as a background // starting service we are waiting for, to also include processes that are // currently running other services or receivers. @@ -589,7 +588,7 @@ public final class ActiveServices { "Not delaying, but counting as bg: " + r); } else if (DEBUG_DELAYED_STARTS) { StringBuilder sb = new StringBuilder(128); - sb.append("Not potential delay (state=").append(proc.curProcState) + sb.append("Not potential delay (state=").append(proc.getCurProcState()) .append(' ').append(proc.adjType); String reason = proc.makeAdjReason(); if (reason != null) { @@ -1442,8 +1441,8 @@ public final class ActiveServices { } } } - if (anyClientActivities != proc.hasClientActivities) { - proc.hasClientActivities = anyClientActivities; + if (anyClientActivities != proc.hasClientActivities()) { + proc.setHasClientActivities(anyClientActivities); if (updateLru) { mAm.updateLruProcessLocked(proc, anyClientActivities, null); } @@ -1623,8 +1622,9 @@ public final class ActiveServices { } } - mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState, - s.appInfo.uid, s.appInfo.longVersionCode, s.name, s.processName); + mAm.startAssociationLocked(callerApp.uid, callerApp.processName, + callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode, + s.name, s.processName); // Once the apps have become associated, if one of them is caller is ephemeral // the target app should now be able to see the calling app mAm.grantEphemeralAccessLocked(callerApp.userId, service, @@ -1680,7 +1680,7 @@ public final class ActiveServices { s.app.whitelistManager = true; } // This could have made the service more important. - mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities + mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities() || s.app.treatLikeActivity, b.client); mAm.updateOomAdjLocked(s.app, true); } @@ -1794,7 +1794,7 @@ public final class ActiveServices { if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { r.binding.service.app.treatLikeActivity = true; mAm.updateLruProcessLocked(r.binding.service.app, - r.binding.service.app.hasClientActivities + r.binding.service.app.hasClientActivities() || r.binding.service.app.treatLikeActivity, null); } mAm.updateOomAdjLocked(r.binding.service.app, false); @@ -3259,9 +3259,9 @@ public final class ActiveServices { } } - void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) { + void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { ArrayList<ServiceRecord> services = new ArrayList<>(); - ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(tr.userId); + ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(userId); for (int i = alls.size() - 1; i >= 0; i--) { ServiceRecord sr = alls.valueAt(i); if (sr.packageName.equals(component.getPackageName())) { diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java index 95a8e2a0aade..fecb5732745e 100644 --- a/services/core/java/com/android/server/am/ActivityDisplay.java +++ b/services/core/java/com/android/server/am/ActivityDisplay.java @@ -37,12 +37,12 @@ import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID; import static com.android.server.am.ActivityDisplayProto.ID; import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY; import static com.android.server.am.ActivityDisplayProto.STACKS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import static com.android.server.am.ActivityStackSupervisor.FindTaskResult; import static com.android.server.am.ActivityStackSupervisor.TAG_STATES; @@ -73,7 +73,7 @@ import java.util.ArrayList; */ class ActivityDisplay extends ConfigurationContainer<ActivityStack> implements WindowContainerListener { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_ATM; private static final String TAG_STACK = TAG + POSTFIX_STACK; static final int POSITION_TOP = Integer.MAX_VALUE; diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 3a0289cbfd63..5c77f0a3ad47 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -220,7 +220,7 @@ final class ActivityManagerConstants extends ContentObserver { // Indicates whether the activity starts logging is enabled. // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED - boolean mFlagActivityStartsLoggingEnabled; + volatile boolean mFlagActivityStartsLoggingEnabled; private final ActivityManagerService mService; private ContentResolver mResolver; diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java index 0e63d0c557f6..0aaea2f62de0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java +++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java @@ -41,97 +41,48 @@ class ActivityManagerDebugConfig { // Enable all debug log categories. static final boolean DEBUG_ALL = false; - // Enable all debug log categories for activities. - static final boolean DEBUG_ALL_ACTIVITIES = DEBUG_ALL || false; - // Available log categories in the activity manager package. - static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false; static final boolean DEBUG_ANR = true; // STOPSHIP disable it (b/113252928) - static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false; static final boolean DEBUG_BACKGROUND_CHECK = DEBUG_ALL || false; static final boolean DEBUG_BACKUP = DEBUG_ALL || false; static final boolean DEBUG_BROADCAST = DEBUG_ALL || false; static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false; static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false; - static final boolean DEBUG_CLEANUP = DEBUG_ALL || false; - static final boolean DEBUG_CONFIGURATION = DEBUG_ALL || false; - static final boolean DEBUG_CONTAINERS = DEBUG_ALL_ACTIVITIES || false; - static final boolean DEBUG_FOCUS = false; - static final boolean DEBUG_IDLE = DEBUG_ALL_ACTIVITIES || false; - static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false; - static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false; static final boolean DEBUG_LRU = DEBUG_ALL || false; static final boolean DEBUG_MU = DEBUG_ALL || false; static final boolean DEBUG_NETWORK = DEBUG_ALL || false; static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false; static final boolean DEBUG_OOM_ADJ_REASON = DEBUG_ALL || false; - static final boolean DEBUG_PAUSE = DEBUG_ALL || false; static final boolean DEBUG_POWER = DEBUG_ALL || false; static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false; static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false; static final boolean DEBUG_PROCESSES = DEBUG_ALL || false; static final boolean DEBUG_PROVIDER = DEBUG_ALL || false; static final boolean DEBUG_PSS = DEBUG_ALL || false; - static final boolean DEBUG_RECENTS = DEBUG_ALL || false; - static final boolean DEBUG_RECENTS_TRIM_TASKS = DEBUG_RECENTS || false; - static final boolean DEBUG_RELEASE = DEBUG_ALL_ACTIVITIES || false; - static final boolean DEBUG_RESULTS = DEBUG_ALL || false; - static final boolean DEBUG_SAVED_STATE = DEBUG_ALL_ACTIVITIES || false; static final boolean DEBUG_SERVICE = DEBUG_ALL || false; static final boolean DEBUG_FOREGROUND_SERVICE = DEBUG_ALL || false; static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false; - static final boolean DEBUG_STACK = DEBUG_ALL || false; - static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false; - static final boolean DEBUG_SWITCH = DEBUG_ALL || false; - static final boolean DEBUG_TASKS = DEBUG_ALL || false; - static final boolean DEBUG_TRANSITION = DEBUG_ALL || false; static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false; - static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false; - static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false; - static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false; static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false; static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false; static final boolean DEBUG_WHITELISTS = DEBUG_ALL || false; - static final boolean DEBUG_METRICS = DEBUG_ALL || false; - static final String POSTFIX_ADD_REMOVE = (APPEND_CATEGORY_NAME) ? "_AddRemove" : ""; - static final String POSTFIX_APP = (APPEND_CATEGORY_NAME) ? "_App" : ""; static final String POSTFIX_BACKUP = (APPEND_CATEGORY_NAME) ? "_Backup" : ""; static final String POSTFIX_BROADCAST = (APPEND_CATEGORY_NAME) ? "_Broadcast" : ""; static final String POSTFIX_CLEANUP = (APPEND_CATEGORY_NAME) ? "_Cleanup" : ""; - static final String POSTFIX_CONFIGURATION = (APPEND_CATEGORY_NAME) ? "_Configuration" : ""; - static final String POSTFIX_CONTAINERS = (APPEND_CATEGORY_NAME) ? "_Containers" : ""; - static final String POSTFIX_FOCUS = (APPEND_CATEGORY_NAME) ? "_Focus" : ""; - static final String POSTFIX_IDLE = (APPEND_CATEGORY_NAME) ? "_Idle" : ""; - static final String POSTFIX_IMMERSIVE = (APPEND_CATEGORY_NAME) ? "_Immersive" : ""; - static final String POSTFIX_LOCKTASK = (APPEND_CATEGORY_NAME) ? "_LockTask" : ""; static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : ""; static final String POSTFIX_MU = "_MU"; static final String POSTFIX_NETWORK = "_Network"; static final String POSTFIX_OOM_ADJ = (APPEND_CATEGORY_NAME) ? "_OomAdj" : ""; - static final String POSTFIX_PAUSE = (APPEND_CATEGORY_NAME) ? "_Pause" : ""; static final String POSTFIX_POWER = (APPEND_CATEGORY_NAME) ? "_Power" : ""; static final String POSTFIX_PROCESS_OBSERVERS = (APPEND_CATEGORY_NAME) ? "_ProcessObservers" : ""; static final String POSTFIX_PROCESSES = (APPEND_CATEGORY_NAME) ? "_Processes" : ""; static final String POSTFIX_PROVIDER = (APPEND_CATEGORY_NAME) ? "_Provider" : ""; static final String POSTFIX_PSS = (APPEND_CATEGORY_NAME) ? "_Pss" : ""; - static final String POSTFIX_RECENTS = (APPEND_CATEGORY_NAME) ? "_Recents" : ""; - static final String POSTFIX_RELEASE = (APPEND_CATEGORY_NAME) ? "_Release" : ""; - static final String POSTFIX_RESULTS = (APPEND_CATEGORY_NAME) ? "_Results" : ""; - static final String POSTFIX_SAVED_STATE = (APPEND_CATEGORY_NAME) ? "_SavedState" : ""; static final String POSTFIX_SERVICE = (APPEND_CATEGORY_NAME) ? "_Service" : ""; static final String POSTFIX_SERVICE_EXECUTING = (APPEND_CATEGORY_NAME) ? "_ServiceExecuting" : ""; - static final String POSTFIX_STACK = (APPEND_CATEGORY_NAME) ? "_Stack" : ""; - static final String POSTFIX_STATES = (APPEND_CATEGORY_NAME) ? "_States" : ""; - static final String POSTFIX_SWITCH = (APPEND_CATEGORY_NAME) ? "_Switch" : ""; - static final String POSTFIX_TASKS = (APPEND_CATEGORY_NAME) ? "_Tasks" : ""; - static final String POSTFIX_TRANSITION = (APPEND_CATEGORY_NAME) ? "_Transition" : ""; static final String POSTFIX_UID_OBSERVERS = (APPEND_CATEGORY_NAME) ? "_UidObservers" : ""; - static final String POSTFIX_URI_PERMISSION = (APPEND_CATEGORY_NAME) ? "_UriPermission" : ""; - static final String POSTFIX_USER_LEAVING = (APPEND_CATEGORY_NAME) ? "_UserLeaving" : ""; - static final String POSTFIX_VISIBILITY = (APPEND_CATEGORY_NAME) ? "_Visibility" : ""; - } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index acf7a73332b7..d5b618f954df 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -91,7 +91,6 @@ import static android.provider.Settings.Global.DEBUG_APP; import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS; import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER; import static android.text.format.DateUtils.DAY_IN_MILLIS; -import static android.view.Display.DEFAULT_DISPLAY; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR; @@ -100,9 +99,9 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK; @@ -115,15 +114,15 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBS import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LRU; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_NETWORK; @@ -134,7 +133,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROCESS_O import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROVIDER; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -202,7 +201,6 @@ import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy; -import android.content.pm.ConfigurationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; @@ -267,7 +265,6 @@ import android.os.TransactionTooLargeException; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; -import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManagerInternal; import android.provider.Settings; @@ -341,7 +338,6 @@ import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; -import com.android.server.am.ActivityStack.ActivityState; import com.android.server.am.MemoryStatUtil.MemoryStat; import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; @@ -434,7 +430,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final boolean MONITOR_THREAD_CPU_USAGE = false; // The flags that are set for all calls we make to the package manager. - static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES; + public static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES; static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; @@ -464,7 +460,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Must be kept in sync with Am. private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0; - static final int MY_PID = myPid(); + public static final int MY_PID = myPid(); static final String[] EMPTY_STRING_ARRAY = new String[0]; @@ -485,9 +481,6 @@ public class ActivityManagerService extends IActivityManager.Stub private static final String INTENT_REMOTE_BUGREPORT_FINISHED = "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED"; - // Used to indicate that an app transition should be animated. - static final boolean ANIMATE = true; - // If set, we will push process association information in to procstats. static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true; @@ -1053,11 +1046,6 @@ public class ActivityManagerService extends IActivityManager.Stub final AppOpsService mAppOpsService; /** - * Hardware-reported OpenGLES version. - */ - final int GL_ES_VERSION; - - /** * List of initialization arguments to pass to all processes when binding applications to them. * For example, references to the commonly used services. */ @@ -1077,7 +1065,6 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") boolean mCallFinishBooting = false; @GuardedBy("this") boolean mBootAnimationComplete = false; - private @GuardedBy("this") boolean mCheckedForSetup = false; final Context mContext; @@ -1405,7 +1392,6 @@ public class ActivityManagerService extends IActivityManager.Stub static final int SHOW_ERROR_UI_MSG = 1; static final int SHOW_NOT_RESPONDING_UI_MSG = 2; - static final int UPDATE_CONFIGURATION_MSG = 4; static final int GC_BACKGROUND_PROCESSES_MSG = 5; static final int WAIT_FOR_DEBUGGER_UI_MSG = 6; static final int SERVICE_TIMEOUT_MSG = 12; @@ -1420,7 +1406,6 @@ public class ActivityManagerService extends IActivityManager.Stub static final int DISPATCH_PROCESS_DIED_UI_MSG = 32; static final int REPORT_MEM_USAGE_MSG = 33; static final int UPDATE_TIME_PREFERENCE_MSG = 41; - static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47; static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49; static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50; static final int DELETE_DUMPHEAP_MSG = 51; @@ -1434,10 +1419,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int SERVICE_FOREGROUND_CRASH_MSG = 69; static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70; - static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; - static final int FIRST_COMPAT_MODE_MSG = 300; - static final int FIRST_SUPERVISOR_STACK_MSG = 100; static final String SERVICE_RECORD_KEY = "servicerecord"; @@ -1600,11 +1582,6 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void handleMessage(Message msg) { switch (msg.what) { - case UPDATE_CONFIGURATION_MSG: { - final ContentResolver resolver = mContext.getContentResolver(); - Settings.System.putConfigurationForUser(resolver, (Configuration) msg.obj, - msg.arg1); - } break; case GC_BACKGROUND_PROCESSES_MSG: { synchronized (ActivityManagerService.this) { performAppGcsIfAppropriateLocked(); @@ -1735,18 +1712,6 @@ public class ActivityManagerService extends IActivityManager.Stub } break; } - case SEND_LOCALE_TO_MOUNT_DAEMON_MSG: { - try { - Locale l = (Locale) msg.obj; - IBinder service = ServiceManager.getService("mount"); - IStorageManager storageManager = IStorageManager.Stub.asInterface(service); - Log.d(TAG, "Storing locale " + l.toLanguageTag() + " for decryption UI"); - storageManager.setField(StorageManager.SYSTEM_LOCALE_KEY, l.toLanguageTag()); - } catch (RemoteException e) { - Log.e(TAG, "Error storing locale for decryption UI", e); - } - break; - } case NOTIFY_CLEARTEXT_NETWORK_MSG: { final int uid = msg.arg1; final byte[] firstPacket = (byte[]) msg.obj; @@ -2058,6 +2023,7 @@ public class ActivityManagerService extends IActivityManager.Stub public void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) { mUsageStatsService = usageStatsManager; + mActivityTaskManager.setUsageStatsManager(usageStatsManager); } public void startObservingNativeCrashes() { @@ -2297,7 +2263,6 @@ public class ActivityManagerService extends IActivityManager.Stub mInjector = injector; mContext = mInjector.getContext(); mUiContext = null; - GL_ES_VERSION = 0; mAppErrors = null; mAppOpsService = mInjector.getAppOpsService(null, null); mBatteryStatsService = null; @@ -2387,9 +2352,6 @@ public class ActivityManagerService extends IActivityManager.Stub mPendingIntentController = new PendingIntentController( mHandlerThread.getLooper(), mUserController); - GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", - ConfigurationInfo.GL_ES_VERSION_UNDEFINED); - if (SystemProperties.getInt("sys.use_fifo_ui", 0) != 0) { mUseFifoUiScheduling = true; } @@ -2398,7 +2360,8 @@ public class ActivityManagerService extends IActivityManager.Stub mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler); mActivityTaskManager = atm; - mActivityTaskManager.setActivityManagerService(this); + mActivityTaskManager.setActivityManagerService(this, mHandlerThread.getLooper(), + mIntentFirewall, mPendingIntentController); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mStackSupervisor = mActivityTaskManager.mStackSupervisor; @@ -2834,7 +2797,7 @@ public class ActivityManagerService extends IActivityManager.Stub final void updateLruProcessLocked(ProcessRecord app, boolean activityChange, ProcessRecord client) { - final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities + final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities() || app.treatLikeActivity; final boolean hasService = false; // not impl yet. app.services.size() > 0; if (!activityChange && hasActivity) { @@ -3693,14 +3656,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - boolean getCheckedForSetup() { - return mCheckedForSetup; - } - - void setCheckedForSetup(boolean checked) { - mCheckedForSetup = checked; - } - CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) { return mAtmInternal.compatibilityInfoForPackage(ai); } @@ -3764,7 +3719,7 @@ public class ActivityManagerService extends IActivityManager.Stub "Unable to set a higher trim level than current level"); } if (!(level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN || - app.curProcState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)) { + app.getCurProcState() > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)) { throw new IllegalArgumentException("Unable to set a background trim level " + "on a foreground process"); } @@ -6550,7 +6505,7 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i = 0; i < pids.length; i++) { ProcessRecord pr = mPidsSelfLocked.get(pids[i]); states[i] = (pr == null) ? ActivityManager.PROCESS_STATE_NONEXISTENT : - pr.curProcState; + pr.getCurProcState(); if (scores != null) { scores[i] = (pr == null) ? ProcessList.INVALID_ADJ : pr.curAdj; } @@ -6834,7 +6789,7 @@ public class ActivityManagerService extends IActivityManager.Stub proc = mPidsSelfLocked.get(callingPid); } if (proc != null && - !ActivityManager.isProcStateBackground(proc.curProcState)) { + !ActivityManager.isProcStateBackground(proc.getCurProcState())) { // Whoever is instigating this is in the foreground, so we will allow it // to go through. return ActivityManager.APP_START_MODE_NORMAL; @@ -6871,11 +6826,6 @@ public class ActivityManagerService extends IActivityManager.Stub return ptw != null ? ptw.tag : null; } - @VisibleForTesting - boolean isActivityStartsLoggingEnabled() { - return mConstants.mFlagActivityStartsLoggingEnabled; - } - private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) { ProviderInfo pi = null; ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userHandle); @@ -7415,7 +7365,7 @@ public class ActivityManagerService extends IActivityManager.Stub } cpr.connections.add(conn); r.conProviders.add(conn); - startAssociationLocked(r.uid, r.processName, r.curProcState, + startAssociationLocked(r.uid, r.processName, r.getCurProcState(), cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); return conn; } @@ -9250,11 +9200,11 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, "setHasTopUi called on unknown pid: " + pid); return; } - if (pr.hasTopUi != hasTopUi) { + if (pr.hasTopUi() != hasTopUi) { if (DEBUG_OOM_ADJ) { Slog.d(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid); } - pr.hasTopUi = hasTopUi; + pr.setHasTopUi(hasTopUi); changed = true; } } @@ -10435,10 +10385,10 @@ public class ActivityManagerService extends IActivityManager.Stub } outInfo.lastTrimLevel = app.trimMemoryLevel; int adj = app.curAdj; - int procState = app.curProcState; + int procState = app.getCurProcState(); outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk); outInfo.importanceReasonCode = app.adjTypeCode; - outInfo.processState = app.curProcState; + outInfo.processState = app.getCurProcState(); outInfo.isFocused = (app == getTopAppLocked()); outInfo.lastActivityTime = app.lastActivityTime; } @@ -12662,12 +12612,13 @@ public class ActivityManagerService extends IActivityManager.Stub if (schedGroup != ProcessOomProto.SCHED_GROUP_UNKNOWN) { proto.write(ProcessOomProto.SCHED_GROUP, schedGroup); } - if (r.foregroundActivities) { + if (r.hasForegroundActivities()) { proto.write(ProcessOomProto.ACTIVITIES, true); } else if (r.hasForegroundServices()) { proto.write(ProcessOomProto.SERVICES, true); } - proto.write(ProcessOomProto.STATE, ProcessList.makeProcStateProtoEnum(r.curProcState)); + proto.write(ProcessOomProto.STATE, + ProcessList.makeProcStateProtoEnum(r.getCurProcState())); proto.write(ProcessOomProto.TRIM_MEMORY_LEVEL, r.trimMemoryLevel); r.writeToProto(proto, ProcessOomProto.PROC); proto.write(ProcessOomProto.ADJ_TYPE, r.adjType); @@ -12693,7 +12644,7 @@ public class ActivityManagerService extends IActivityManager.Stub proto.write(ProcessOomProto.Detail.CUR_ADJ, r.curAdj); proto.write(ProcessOomProto.Detail.SET_ADJ, r.setAdj); proto.write(ProcessOomProto.Detail.CURRENT_STATE, - ProcessList.makeProcStateProtoEnum(r.curProcState)); + ProcessList.makeProcStateProtoEnum(r.getCurProcState())); proto.write(ProcessOomProto.Detail.SET_STATE, ProcessList.makeProcStateProtoEnum(r.setProcState)); proto.write(ProcessOomProto.Detail.LAST_PSS, DebugUtils.sizeValueToString( @@ -12759,14 +12710,14 @@ public class ActivityManagerService extends IActivityManager.Stub break; } char foreground; - if (r.foregroundActivities) { + if (r.hasForegroundActivities()) { foreground = 'A'; } else if (r.hasForegroundServices()) { foreground = 'S'; } else { foreground = ' '; } - String procState = ProcessList.makeProcStateString(r.curProcState); + String procState = ProcessList.makeProcStateString(r.getCurProcState()); pw.print(prefix); pw.print(r.isPersistent() ? persistentLabel : normalLabel); pw.print(" #"); @@ -12820,7 +12771,8 @@ public class ActivityManagerService extends IActivityManager.Stub pw.print(" set="); pw.println(r.setAdj); pw.print(prefix); pw.print(" "); - pw.print("state: cur="); pw.print(ProcessList.makeProcStateString(r.curProcState)); + pw.print("state: cur="); pw.print( + ProcessList.makeProcStateString(r.getCurProcState())); pw.print(" set="); pw.print(ProcessList.makeProcStateString(r.setProcState)); pw.print(" lastPss="); DebugUtils.printSizeValue(pw, r.lastPss*1024); pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, r.lastSwapPss*1024); @@ -14610,11 +14562,11 @@ public class ActivityManagerService extends IActivityManager.Stub app.waitingToKill = null; app.forcingToImportant = null; updateProcessForegroundLocked(app, false, false); - app.foregroundActivities = false; + app.setHasForegroundActivities(false); app.hasShownUi = false; app.treatLikeActivity = false; app.hasAboveClient = false; - app.hasClientActivities = false; + app.setHasClientActivities(false); mServices.killServicesLocked(app, allowRestart); @@ -17056,7 +17008,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (app.thread == null) { app.adjSeq = mAdjSeq; app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND); - app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + app.setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY); app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ; app.completedAdjSeq = app.adjSeq; return false; @@ -17073,7 +17025,7 @@ public class ActivityManagerService extends IActivityManager.Stub final int logUid = mCurOomAdjUid; int prevAppAdj = app.curAdj; - int prevProcState = app.curProcState; + int prevProcState = app.getCurProcState(); if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { // The max adjustment doesn't allow this app to be anything @@ -17084,9 +17036,9 @@ public class ActivityManagerService extends IActivityManager.Stub app.adjType = "fixed"; app.adjSeq = mAdjSeq; app.curRawAdj = app.maxAdj; - app.foregroundActivities = false; + app.setHasForegroundActivities(false); app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT); - app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT; + app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT); // System processes can do UI, and when they do we want to have // them trim their memory after the user leaves the UI. To // facilitate this, here we need to determine whether or not it @@ -17096,7 +17048,7 @@ public class ActivityManagerService extends IActivityManager.Stub app.systemNoUi = false; app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); app.adjType = "pers-top-activity"; - } else if (app.hasTopUi) { + } else if (app.hasTopUi()) { // sched group/proc state adjustment is below app.systemNoUi = false; app.adjType = "pers-top-ui"; @@ -17106,11 +17058,11 @@ public class ActivityManagerService extends IActivityManager.Stub if (!app.systemNoUi) { if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) { // screen on, promote UI - app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI; + app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI); app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); } else { // screen off, restrict UI scheduling - app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; + app.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED); } } @@ -17246,7 +17198,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to fg service: " + app); } - } else if (app.hasOverlayUi) { + } else if (app.hasOverlayUi()) { // The process is display an overlay UI. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; @@ -17476,7 +17428,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } int clientAdj = client.curRawAdj; - int clientProcState = client.curProcState; + int clientProcState = client.getCurProcState(); if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. The specific cached state @@ -17637,8 +17589,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND - && (cr.flags&Context.BIND_SHOWING_UI) != 0) { - app.pendingUiClean = true; + && (cr.flags & Context.BIND_SHOWING_UI) != 0) { + app.setPendingUiClean(true); } if (adjType != null) { app.adjType = adjType; @@ -17718,7 +17670,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } int clientAdj = client.curRawAdj; - int clientProcState = client.curProcState; + int clientProcState = client.getCurProcState(); if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. @@ -17879,7 +17831,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) { - if (app.hasClientActivities) { + if (app.hasClientActivities()) { // This is a cached process, but with client activities. Mark it so. procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; app.adjType = "cch-client-act"; @@ -17946,12 +17898,12 @@ public class ActivityManagerService extends IActivityManager.Stub // keep it out of the cached vaues. app.curAdj = app.modifyRawOomAdj(adj); app.setCurrentSchedulingGroup(schedGroup); - app.curProcState = procState; - app.foregroundActivities = foregroundActivities; + app.setCurProcState(procState); + app.setHasForegroundActivities(foregroundActivities); app.completedAdjSeq = mAdjSeq; // if curAdj or curProcState improved, then this process was promoted - return app.curAdj < prevAppAdj || app.curProcState < prevProcState; + return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState; } /** @@ -18103,7 +18055,7 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i = mLruProcesses.size() - 1; i >= 0; i--) { ProcessRecord app = mLruProcesses.get(i); if (app.thread == null - || app.curProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) { + || app.getCurProcState() == ActivityManager.PROCESS_STATE_NONEXISTENT) { continue; } if (memLowered || (always && now > @@ -18112,7 +18064,7 @@ public class ActivityManagerService extends IActivityManager.Stub app.pssProcState = app.setProcState; app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM; - app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, + app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(), app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now); mPendingPssProcesses.add(app); } @@ -18305,7 +18257,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (doCpuKills && uptimeSince > 0) { // What is the limit for this process? int cpuLimit; - long checkDur = curUptime - app.whenUnimportant; + long checkDur = curUptime - app.getWhenUnimportant(); if (checkDur <= mConstants.POWER_CHECK_INTERVAL) { cpuLimit = mConstants.POWER_CHECK_MAX_CPU_1; } else if (checkDur <= (mConstants.POWER_CHECK_INTERVAL*2) @@ -18467,12 +18419,12 @@ public class ActivityManagerService extends IActivityManager.Stub } } } - if (app.repForegroundActivities != app.foregroundActivities) { - app.repForegroundActivities = app.foregroundActivities; + if (app.repForegroundActivities != app.hasForegroundActivities()) { + app.repForegroundActivities = app.hasForegroundActivities(); changes |= ProcessChangeItem.CHANGE_ACTIVITIES; } - if (app.getReportedProcState() != app.curProcState) { - app.setReportedProcState(app.curProcState); + if (app.getReportedProcState() != app.getCurProcState()) { + app.setReportedProcState(app.getCurProcState()); if (app.thread != null) { try { if (false) { @@ -18486,7 +18438,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT - || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) { + || ProcessList.procStatesDifferForMem(app.getCurProcState(), app.setProcState)) { if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now-200)) { // Experimental code to more aggressively collect pss while // running test... the problem is that this tends to collect @@ -18496,46 +18448,45 @@ public class ActivityManagerService extends IActivityManager.Stub long startTime = SystemClock.currentThreadTimeMillis(); long pss = Debug.getPss(app.pid, mTmpLong, null); long endTime = SystemClock.currentThreadTimeMillis(); - recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1], + recordPssSampleLocked(app, app.getCurProcState(), pss, mTmpLong[0], mTmpLong[1], mTmpLong[2], ProcessStats.ADD_PSS_INTERNAL_SINGLE, endTime-startTime, now); mPendingPssProcesses.remove(app); Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState - + " to " + app.curProcState + ": " + + " to " + app.getCurProcState() + ": " + (SystemClock.uptimeMillis()-start) + "ms"); } app.lastStateTime = now; - app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, + app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(), app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now); if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from " + ProcessList.makeProcStateString(app.setProcState) + " to " - + ProcessList.makeProcStateString(app.curProcState) + " next pss in " + + ProcessList.makeProcStateString(app.getCurProcState()) + " next pss in " + (app.nextPssTime-now) + ": " + app); } else { if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL) && now > (app.lastStateTime+ProcessList.minTimeFromStateChange( mTestPssMode)))) { if (requestPssLocked(app, app.setProcState)) { - app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, + app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(), app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now); } } else if (false && DEBUG_PSS) Slog.d(TAG_PSS, "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now)); } - if (app.setProcState != app.curProcState) { + if (app.setProcState != app.getCurProcState()) { if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) { String msg = "Proc state change of " + app.processName - + " to " + ProcessList.makeProcStateString(app.curProcState) - + " (" + app.curProcState + ")" + ": " + app.adjType; + + " to " + ProcessList.makeProcStateString(app.getCurProcState()) + + " (" + app.getCurProcState() + ")" + ": " + app.adjType; reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); } boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE; - boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE; + boolean curImportant = app.getCurProcState() < ActivityManager.PROCESS_STATE_SERVICE; if (setImportant && !curImportant) { - // This app is no longer something we consider important enough to allow to - // use arbitrary amounts of battery power. Note - // its current CPU time to later know to kill it if - // it is not behaving well. - app.whenUnimportant = now; + // This app is no longer something we consider important enough to allow to use + // arbitrary amounts of battery power. Note its current CPU time to later know to + // kill it if it is not behaving well. + app.setWhenUnimportant(now); app.lastCpuTime = 0; } // Inform UsageStats of important process state change @@ -18544,7 +18495,7 @@ public class ActivityManagerService extends IActivityManager.Stub maybeUpdateLastTopTime(app, now); - app.setProcState = app.curProcState; + app.setProcState = app.getCurProcState(); if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) { app.notCachedSinceIdle = false; } @@ -18553,7 +18504,7 @@ public class ActivityManagerService extends IActivityManager.Stub } else { app.procStateChanged = true; } - } else if (app.reportedInteraction && (nowElapsed-app.interactionEventTime) + } else if (app.reportedInteraction && (nowElapsed - app.getInteractionEventTime()) > mConstants.USAGE_STATS_INTERACTION_INTERVAL) { // For apps that sit around for a long time in the interactive state, we need // to report this at least once a day so they don't go idle. @@ -18707,7 +18658,7 @@ public class ActivityManagerService extends IActivityManager.Stub private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName, String authority) { if (app == null) return; - if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { + if (app.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { UserState userState = mUserController.getStartedUserState(app.userId); if (userState == null) return; final long now = SystemClock.elapsedRealtime(); @@ -18727,7 +18678,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_USAGE_STATS) { Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList()) + "] state changes: old = " + app.setProcState + ", new = " - + app.curProcState); + + app.getCurProcState()); } if (mUsageStatsService == null) { return; @@ -18736,24 +18687,26 @@ public class ActivityManagerService extends IActivityManager.Stub // To avoid some abuse patterns, we are going to be careful about what we consider // to be an app interaction. Being the top activity doesn't count while the display // is sleeping, nor do short foreground services. - if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP) { + if (app.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP) { isInteraction = true; - app.fgInteractionTime = 0; - } else if (app.curProcState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { - if (app.fgInteractionTime == 0) { - app.fgInteractionTime = nowElapsed; + app.setFgInteractionTime(0); + } else if (app.getCurProcState() <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { + if (app.getFgInteractionTime() == 0) { + app.setFgInteractionTime(nowElapsed); isInteraction = false; } else { - isInteraction = nowElapsed > app.fgInteractionTime + isInteraction = nowElapsed > app.getFgInteractionTime() + mConstants.SERVICE_USAGE_INTERACTION_TIME; } } else { - isInteraction = app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; - app.fgInteractionTime = 0; + isInteraction = + app.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + app.setFgInteractionTime(0); } - if (isInteraction && (!app.reportedInteraction || (nowElapsed-app.interactionEventTime) + if (isInteraction + && (!app.reportedInteraction || (nowElapsed - app.getInteractionEventTime()) > mConstants.USAGE_STATS_INTERACTION_INTERVAL)) { - app.interactionEventTime = nowElapsed; + app.setInteractionEventTime(nowElapsed); String[] packages = app.getPackageList(); if (packages != null) { for (int i = 0; i < packages.length; i++) { @@ -18764,13 +18717,13 @@ public class ActivityManagerService extends IActivityManager.Stub } app.reportedInteraction = isInteraction; if (!isInteraction) { - app.interactionEventTime = 0; + app.setInteractionEventTime(0); } } private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) { if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP - && app.curProcState > ActivityManager.PROCESS_STATE_TOP) { + && app.getCurProcState() > ActivityManager.PROCESS_STATE_TOP) { app.lastTopTime = nowUptime; } } @@ -18991,7 +18944,7 @@ public class ActivityManagerService extends IActivityManager.Stub // If we haven't yet assigned the final cached adj // to the process, do that now. if (app.curAdj >= ProcessList.UNKNOWN_ADJ) { - switch (app.curProcState) { + switch (app.getCurProcState()) { case PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: case ActivityManager.PROCESS_STATE_CACHED_RECENT: @@ -19079,7 +19032,7 @@ public class ActivityManagerService extends IActivityManager.Stub applyOomAdjLocked(app, true, now, nowElapsed); // Count the number of process types. - switch (app.curProcState) { + switch (app.getCurProcState()) { case PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: mNumCachedHiddenProcs++; @@ -19120,8 +19073,8 @@ public class ActivityManagerService extends IActivityManager.Stub final UidRecord uidRec = app.uidRecord; if (uidRec != null) { uidRec.ephemeral = app.info.isInstantApp(); - if (uidRec.curProcState > app.curProcState) { - uidRec.curProcState = app.curProcState; + if (uidRec.curProcState > app.getCurProcState()) { + uidRec.curProcState = app.getCurProcState(); } if (app.hasForegroundServices()) { uidRec.foregroundServices = true; @@ -19129,7 +19082,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } - if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME + if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME && !app.killedByAm) { numTrimming++; } @@ -19212,7 +19165,7 @@ public class ActivityManagerService extends IActivityManager.Stub setProcessTrackerStateLocked(app, trackerMemFactor, now); app.procStateChanged = false; } - if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME + if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME && !app.killedByAm) { if (app.trimMemoryLevel < curLevel && app.thread != null) { try { @@ -19235,7 +19188,7 @@ public class ActivityManagerService extends IActivityManager.Stub break; } } - } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT + } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT && !app.killedByAm) { if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND && app.thread != null) { @@ -19250,8 +19203,8 @@ public class ActivityManagerService extends IActivityManager.Stub } app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; } else { - if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND - || app.systemNoUi) && app.pendingUiClean) { + if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND + || app.systemNoUi) && app.hasPendingUiClean()) { // If this application is now in the background and it // had done UI, then give it the special trim level to // have it free UI resources. @@ -19265,7 +19218,7 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException e) { } } - app.pendingUiClean = false; + app.setPendingUiClean(false); } if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) { try { @@ -19290,8 +19243,8 @@ public class ActivityManagerService extends IActivityManager.Stub setProcessTrackerStateLocked(app, trackerMemFactor, now); app.procStateChanged = false; } - if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND - || app.systemNoUi) && app.pendingUiClean) { + if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND + || app.systemNoUi) && app.hasPendingUiClean()) { if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN && app.thread != null) { try { @@ -19303,7 +19256,7 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException e) { } } - app.pendingUiClean = false; + app.setPendingUiClean(false); } app.trimMemoryLevel = 0; } @@ -20320,7 +20273,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (app.removed) { procs.add(app); - } else if (app.userId == userHandle && app.foregroundActivities) { + } else if (app.userId == userHandle && app.hasForegroundActivities()) { app.removed = true; procs.add(app); } @@ -20391,10 +20344,10 @@ public class ActivityManagerService extends IActivityManager.Stub return; } } - if (pr.hasOverlayUi == hasOverlayUi) { + if (pr.hasOverlayUi() == hasOverlayUi) { return; } - pr.hasOverlayUi = hasOverlayUi; + pr.setHasOverlayUi(hasOverlayUi); //Slog.i(TAG, "Setting hasOverlayUi=" + pr.hasOverlayUi + " for pid=" + pid); updateOomAdjLocked(pr, true); } @@ -20779,6 +20732,42 @@ public class ActivityManagerService extends IActivityManager.Stub (ConnectionRecord) cr, null, c)); } } + + public void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { + synchronized(ActivityManagerService.this) { + mServices.cleanUpServices(userId, component, baseIntent); + } + } + + public ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) { + // Locked intentionally not held as it isn't needed for this case. + return ActivityManagerService.this.getActivityInfoForUser(aInfo, userId); + } + + public void ensureBootCompleted() { + // Locked intentionally not held as it isn't needed for this case. + ActivityManagerService.this.ensureBootCompleted(); + } + + public void updateOomLevelsForDisplay(int displayId) { + synchronized(ActivityManagerService.this) { + if (mWindowManager != null) { + mProcessList.applyDisplaySize(mWindowManager); + } + } + } + + public boolean isActivityStartsLoggingEnabled() { + return mConstants.mFlagActivityStartsLoggingEnabled; + } + + public void reportCurKeyguardUsageEvent(boolean keyguardShowing) { + synchronized(ActivityManagerService.this) { + ActivityManagerService.this.reportGlobalUsageEventLocked(keyguardShowing + ? UsageEvents.Event.KEYGUARD_SHOWN + : UsageEvents.Event.KEYGUARD_HIDDEN); + } + } } /** diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 40c555f8c2e6..9f768a84d223 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -23,7 +23,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; -import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import android.app.ActivityManager; import android.app.ActivityOptions; diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 7080e2bd58fd..2620e1e85565 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -72,9 +72,9 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_T import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_METRICS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME; import static com.android.server.am.MemoryStatUtil.MemoryStat; import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; @@ -114,7 +114,7 @@ import com.android.server.LocalServices; */ class ActivityMetricsLogger { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_ATM; // Window modes we are interested in logging. If we ever introduce a new type, we need to add // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array. @@ -230,14 +230,14 @@ class ActivityMetricsLogger { launchedActivityLaunchToken = launchedActivity.info.launchToken; launchedActivityAppRecordRequiredAbi = launchedActivity.app == null ? null - : info.launchedActivity.app.getRequiredAbi(); + : launchedActivity.app.getRequiredAbi(); reason = info.reason; startingWindowDelayMs = info.startingWindowDelayMs; bindApplicationDelayMs = info.bindApplicationDelayMs; windowsDrawnDelayMs = info.windowsDrawnDelayMs; type = getTransitionType(info); - processRecord = findProcessForActivity(info.launchedActivity); - processName = info.launchedActivity.processName; + processRecord = findProcessForActivity(launchedActivity); + processName = launchedActivity.processName; userId = launchedActivity.userId; launchedActivityShortComponentName = launchedActivity.shortComponentName; activityRecordIdHashCode = System.identityHashCode(launchedActivity); @@ -741,7 +741,7 @@ class ActivityMetricsLogger { Log.i(TAG, sb.toString()); } - void logActivityStart(Intent intent, ProcessRecord callerApp, ActivityRecord r, + void logActivityStart(Intent intent, WindowProcessController callerApp, ActivityRecord r, int callingUid, String callingPackage, int callingUidProcState, boolean callingUidHasAnyVisibleWindow, int realCallingUid, int realCallingUidProcState, @@ -776,31 +776,31 @@ class ActivityMetricsLogger { builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0); builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction()); if (callerApp != null) { - builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.processName); + builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.mName); builder.addTaggedData(FIELD_PROCESS_RECORD_CUR_PROC_STATE, - processStateAmToProto(callerApp.curProcState)); + processStateAmToProto(callerApp.getCurrentProcState())); builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES, - callerApp.hasClientActivities ? 1 : 0); + callerApp.hasClientActivities() ? 1 : 0); builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES, callerApp.hasForegroundServices() ? 1 : 0); builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES, - callerApp.foregroundActivities ? 1 : 0); - builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_TOP_UI, callerApp.hasTopUi ? 1 : 0); + callerApp.hasForegroundActivities() ? 1 : 0); + builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_TOP_UI, callerApp.hasTopUi() ? 1 : 0); builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_OVERLAY_UI, - callerApp.hasOverlayUi ? 1 : 0); + callerApp.hasOverlayUi() ? 1 : 0); builder.addTaggedData(FIELD_PROCESS_RECORD_PENDING_UI_CLEAN, - callerApp.pendingUiClean ? 1 : 0); - if (callerApp.interactionEventTime != 0) { + callerApp.hasPendingUiClean() ? 1 : 0); + if (callerApp.getInteractionEventTime() != 0) { builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT, - (nowElapsed - callerApp.interactionEventTime)); + (nowElapsed - callerApp.getInteractionEventTime())); } - if (callerApp.fgInteractionTime != 0) { + if (callerApp.getFgInteractionTime() != 0) { builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION, - (nowElapsed - callerApp.fgInteractionTime)); + (nowElapsed - callerApp.getFgInteractionTime())); } - if (callerApp.whenUnimportant != 0) { + if (callerApp.getWhenUnimportant() != 0) { builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT, - (nowUptime - callerApp.whenUnimportant)); + (nowUptime - callerApp.getWhenUnimportant())); } } builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 6bdceb22d866..d837118f05d4 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -83,20 +83,20 @@ import static android.os.Build.VERSION_CODES.O; import static android.os.Process.SYSTEM_UID; import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_FOCUS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER; import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK; import static com.android.server.am.ActivityRecordProto.IDENTIFIER; @@ -118,7 +118,7 @@ import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY; import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY; import static com.android.server.am.TaskPersister.DEBUG; import static com.android.server.am.TaskPersister.IMAGE_EXTENSION; -import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; @@ -211,7 +211,7 @@ import java.util.Objects; * An entry in the history stack, representing an activity. */ final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM; private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE; private static final String TAG_STATES = TAG + POSTFIX_STATES; @@ -852,13 +852,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } - ActivityRecord(ActivityTaskManagerService _service, ProcessRecord _caller, int _launchedFromPid, - int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, - ActivityInfo aInfo, Configuration _configuration, - ActivityRecord _resultTo, String _resultWho, int _reqCode, - boolean _componentSpecified, boolean _rootVoiceInteraction, - ActivityStackSupervisor supervisor, ActivityOptions options, - ActivityRecord sourceRecord) { + ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller, + int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent, + String _resolvedType, ActivityInfo aInfo, Configuration _configuration, + ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified, + boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, + ActivityOptions options, ActivityRecord sourceRecord) { service = _service; appToken = new Token(this, _intent); info = aInfo; @@ -928,8 +927,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null && (aInfo.applicationInfo.uid == SYSTEM_UID - || aInfo.applicationInfo.uid == _caller.info.uid)) { - processName = _caller.processName; + || aInfo.applicationInfo.uid == _caller.mInfo.uid)) { + processName = _caller.mName; } else { processName = aInfo.processName; } @@ -1783,7 +1782,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } setVisible(true); sleeping = false; - app.setPendingUiClean(true); + app.postPendingUiCleanMsg(true); if (reportToClient) { makeClientVisible(); } else { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 864bf2d77b59..d6a47d8951d5 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -48,39 +48,39 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM; import static com.android.server.am.ActivityDisplay.POSITION_TOP; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TRANSITION; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_APP; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_APP; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PAUSE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RESULTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_APP; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TRANSITION; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_FREE_RESIZE; import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_WINDOWING_MODE_RESIZE; import static com.android.server.am.ActivityStack.ActivityState.DESTROYED; @@ -103,6 +103,7 @@ import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; +import static com.android.server.am.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG; import static java.lang.Integer.MAX_VALUE; import android.app.Activity; @@ -172,7 +173,7 @@ import java.util.Set; */ class ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_APP = TAG + POSTFIX_APP; private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP; @@ -364,12 +365,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai private boolean mTopActivityOccludesKeyguard; private ActivityRecord mTopDismissingKeyguardActivity; - static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1; - static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2; - static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3; - static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4; - static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5; - static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6; + static final int PAUSE_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1; + static final int DESTROY_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 2; + static final int LAUNCH_TICK_MSG = FIRST_ACTIVITY_STACK_MSG + 3; + static final int STOP_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 4; + static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5; + static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6; private static class ScheduleDestroyArgs { final WindowProcessController mOwner; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 8c8146c54d9f..3f823ae8c631 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -54,27 +54,27 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.TYPE_VIRTUAL; import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IDLE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IDLE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.ActivityManagerService.ANIMATE; -import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_IDLE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PAUSE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_IDLE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerService.ANIMATE; +import static com.android.server.am.ActivityTaskManagerService.H.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_NONE; import static com.android.server.am.ActivityStack.ActivityState.DESTROYED; import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING; @@ -91,7 +91,7 @@ import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER; import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES; import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY; -import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; @@ -198,7 +198,7 @@ import java.util.Set; public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener, RecentTasks.Callbacks, RootWindowContainerListener { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_ATM; private static final String TAG_IDLE = TAG + POSTFIX_IDLE; private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; @@ -1487,7 +1487,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } app.hasShownUi = true; - app.pendingUiClean = true; + app.setPendingUiClean(true); app.forceProcessStateUpTo(mService.mTopProcessState); // Because we could be starting an Activity in the system process this may not go // across a Binder interface which would create a new Configuration. Consequently @@ -1717,24 +1717,25 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D sendHint = noResumedActivities || allFocusedProcessesDiffer; } - if (sendHint && mService.mAm.mLocalPowerManager != null) { - mService.mAm.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1); + if (sendHint && mService.mPowerManagerInternal != null) { + mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1); mPowerHintSent = true; } } void sendPowerHintForLaunchEndIfNeeded() { // Trigger launch power hint if activity is launched - if (mPowerHintSent && mService.mAm.mLocalPowerManager != null) { - mService.mAm.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0); + if (mPowerHintSent && mService.mPowerManagerInternal != null) { + mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0); mPowerHintSent = false; } } - boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, - String resultWho, int requestCode, int callingPid, int callingUid, - String callingPackage, boolean ignoreTargetSecurity, boolean launchingInTask, - ProcessRecord callerApp, ActivityRecord resultRecord, ActivityStack resultStack) { + boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho, + int requestCode, int callingPid, int callingUid, String callingPackage, + boolean ignoreTargetSecurity, boolean launchingInTask, + WindowProcessController callerApp, ActivityRecord resultRecord, + ActivityStack resultStack) { final boolean isCallerRecents = mService.getRecentTasks() != null && mService.getRecentTasks().isCallerRecents(callingUid); final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, @@ -3072,7 +3073,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } // Find any running services associated with this app and stop if needed. - mService.mAm.mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent())); + final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::cleanUpServices, + mService.mAmInternal, tr.userId, component, new Intent(tr.getBaseIntent())); + mService.mH.sendMessage(msg); if (!killProcess) { return; @@ -3422,7 +3425,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D throw new IllegalStateException("Calling must be system uid"); } mLaunchingActivity.release(); - mService.mAm.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); + mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); } } diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java index f6f1e5508957..20d5ab201307 100644 --- a/services/core/java/com/android/server/am/ActivityStartController.java +++ b/services/core/java/com/android/server/am/ActivityStartController.java @@ -22,8 +22,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.app.ActivityOptions; import android.app.IApplicationThread; @@ -65,7 +65,7 @@ import java.util.List; * through the pending activity list, and recording home activity launches. */ public class ActivityStartController { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStartController" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStartController" : TAG_ATM; private static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 1; @@ -91,6 +91,8 @@ public class ActivityStartController { private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry; + boolean mCheckedForSetup = false; + private final class StartHandler extends Handler { public StartHandler(Looper looper) { super(looper, null, true); @@ -193,7 +195,7 @@ public class ActivityStartController { */ void startSetupActivity() { // Only do this once per boot. - if (mService.mAm.getCheckedForSetup()) { + if (mCheckedForSetup) { return; } @@ -203,7 +205,7 @@ public class ActivityStartController { final ContentResolver resolver = mService.mContext.getContentResolver(); if (mService.mFactoryTest != FACTORY_TEST_LOW_LEVEL && Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0) { - mService.mAm.setCheckedForSetup(true); + mCheckedForSetup = true; // See if we should be showing the platform update setup UI. final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP); @@ -357,7 +359,7 @@ public class ActivityStartController { null, userId, ActivityStarter.computeResolveFilterUid( callingUid, realCallingUid, UserHandle.USER_NULL)); // TODO: New, check if this is correct - aInfo = mService.mAm.getActivityInfoForUser(aInfo, userId); + aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId); if (aInfo != null && (aInfo.applicationInfo.privateFlags diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java index 4789ff334398..e51824f6f790 100644 --- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java @@ -44,6 +44,7 @@ import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.os.Binder; import android.os.Bundle; @@ -246,9 +247,9 @@ class ActivityStartInterceptor { if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) { return interceptSuspendedByAdminPackage(); } - final String dialogMessage = pmi.getSuspendedDialogMessage(suspendedPackage, mUserId); + final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage, mUserId); mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage, - suspendingPackage, dialogMessage, mUserId); + suspendingPackage, dialogInfo, mUserId); mCallingPid = mRealCallingPid; mCallingUid = mRealCallingUid; mResolvedType = null; diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index fcaced2536a9..afcf9f98caa2 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -53,20 +53,20 @@ import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.ActivityManagerService.ANIMATE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_FOCUS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RESULTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerService.ANIMATE; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; @@ -127,7 +127,7 @@ import java.util.Date; * an activity and associated task and stack. */ class ActivityStarter { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_ATM; private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS; private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS; private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; @@ -590,12 +590,12 @@ class ActivityStarter { final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null; - ProcessRecord callerApp = null; + WindowProcessController callerApp = null; if (caller != null) { - callerApp = mService.mAm.getRecordForAppLocked(caller); + callerApp = mService.getProcessController(caller); if (callerApp != null) { - callingPid = callerApp.pid; - callingUid = callerApp.info.uid; + callingPid = callerApp.getPid(); + callingUid = callerApp.mInfo.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " @@ -726,14 +726,12 @@ class ActivityStarter { boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, inTask != null, callerApp, resultRecord, resultStack); - abort |= !mService.mAm.mIntentFirewall.checkStartActivity(intent, callingUid, + abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); - final WindowProcessController callerWpc = - callerApp != null ? callerApp.getWindowProcessController() : null; // Merge the two options bundles, while realCallerOptions takes precedence. ActivityOptions checkedOptions = options != null - ? options.getOptions(intent, aInfo, callerWpc, mSupervisor) : null; + ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null; if (allowPendingRemoteAnimationRegistryLookup) { checkedOptions = mService.getActivityStartController() .getPendingRemoteAnimationRegistry() @@ -833,8 +831,7 @@ class ActivityStarter { aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); } - ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, - callingUid, + ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); @@ -857,7 +854,7 @@ class ActivityStarter { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { mController.addPendingActivityLaunch(new PendingActivityLaunch(r, - sourceRecord, startFlags, stack, callerWpc)); + sourceRecord, startFlags, stack, callerApp)); ActivityOptions.abort(checkedOptions); return ActivityManager.START_SWITCHES_CANCELED; } @@ -874,12 +871,11 @@ class ActivityStarter { } private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid, - Intent intent, ProcessRecord callerApp, ActivityRecord r, + Intent intent, WindowProcessController callerApp, ActivityRecord r, PendingIntentRecord originatingPendingIntent) { - boolean callerAppHasForegroundActivity = (callerApp != null) - ? callerApp.foregroundActivities - : false; - if (!mService.mAm.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity + boolean callerAppHasForegroundActivity = + callerApp != null && callerApp.hasForegroundActivities(); + if (!mService.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity || r == null) { // skip logging in this case return; @@ -1085,9 +1081,10 @@ class ActivityStarter { || !heavy.mName.equals(aInfo.processName))) { int appCallingUid = callingUid; if (caller != null) { - ProcessRecord callerApp = mService.mAm.getRecordForAppLocked(caller); + WindowProcessController callerApp = + mService.getProcessController(caller); if (callerApp != null) { - appCallingUid = callerApp.info.uid; + appCallingUid = callerApp.mInfo.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " @@ -1127,7 +1124,7 @@ class ActivityStarter { callingUid, realCallingUid, mRequest.filterCallingUid)); aInfo = rInfo != null ? rInfo.activityInfo : null; if (aInfo != null) { - aInfo = mService.mAm.getActivityInfoForUser(aInfo, userId); + aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId); } } } @@ -1493,8 +1490,9 @@ class ActivityStarter { mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId); - mService.mAm.grantEphemeralAccessLocked(mStartActivity.userId, mIntent, - UserHandle.getAppId(mStartActivity.appInfo.uid), UserHandle.getAppId(mCallingUid)); + mService.getPackageManagerInternalLocked().grantEphemeralAccess( + mStartActivity.userId, mIntent, UserHandle.getAppId(mStartActivity.appInfo.uid), + UserHandle.getAppId(mCallingUid)); if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.getTask().taskId); diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java new file mode 100644 index 000000000000..cf727380ae6b --- /dev/null +++ b/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.am; + +/** + * Common class for the various debug {@link android.util.Log} output configuration relating to + * activities. + */ +public class ActivityTaskManagerDebugConfig { + // All output logs relating to acitvities use the {@link #TAG_ATM} string for tagging their log + // output. This makes it easy to identify the origin of the log message when sifting + // through a large amount of log output from multiple sources. However, it also makes trying + // to figure-out the origin of a log message while debugging the activity manager a little + // painful. By setting this constant to true, log messages from the activity manager package + // will be tagged with their class names instead fot the generic tag. + static final boolean TAG_WITH_CLASS_NAME = false; + + // While debugging it is sometimes useful to have the category name of the log appended to the + // base log tag to make sifting through logs with the same base tag easier. By setting this + // constant to true, the category name of the log point will be appended to the log tag. + private static final boolean APPEND_CATEGORY_NAME = false; + + // Default log tag for the activities. + static final String TAG_ATM = "ActivityTaskManager"; + + // Enable all debug log categories. + static final boolean DEBUG_ALL = false; + + // Enable all debug log categories for activities. + private static final boolean DEBUG_ALL_ACTIVITIES = DEBUG_ALL || false; + + static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_CONFIGURATION = DEBUG_ALL || false; + static final boolean DEBUG_CONTAINERS = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_FOCUS = false; + static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false; + static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false; + static final boolean DEBUG_PAUSE = DEBUG_ALL || false; + static final boolean DEBUG_RECENTS = DEBUG_ALL || false; + static final boolean DEBUG_RECENTS_TRIM_TASKS = DEBUG_RECENTS || false; + static final boolean DEBUG_SAVED_STATE = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_STACK = DEBUG_ALL || false; + static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_SWITCH = DEBUG_ALL || false; + static final boolean DEBUG_TASKS = DEBUG_ALL || false; + static final boolean DEBUG_TRANSITION = DEBUG_ALL || false; + static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false; + static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_IDLE = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_RELEASE = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false; + static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false; + static final boolean DEBUG_RESULTS = DEBUG_ALL || false; + static final boolean DEBUG_CLEANUP = DEBUG_ALL || false; + static final boolean DEBUG_METRICS = DEBUG_ALL || false; + + static final String POSTFIX_APP = APPEND_CATEGORY_NAME ? "_App" : ""; + static final String POSTFIX_IDLE = APPEND_CATEGORY_NAME ? "_Idle" : ""; + static final String POSTFIX_RELEASE = APPEND_CATEGORY_NAME ? "_Release" : ""; + static final String POSTFIX_USER_LEAVING = APPEND_CATEGORY_NAME ? "_UserLeaving" : ""; + static final String POSTFIX_ADD_REMOVE = APPEND_CATEGORY_NAME ? "_AddRemove" : ""; + static final String POSTFIX_CONFIGURATION = APPEND_CATEGORY_NAME ? "_Configuration" : ""; + static final String POSTFIX_CONTAINERS = APPEND_CATEGORY_NAME ? "_Containers" : ""; + static final String POSTFIX_FOCUS = APPEND_CATEGORY_NAME ? "_Focus" : ""; + static final String POSTFIX_IMMERSIVE = APPEND_CATEGORY_NAME ? "_Immersive" : ""; + static final String POSTFIX_LOCKTASK = APPEND_CATEGORY_NAME ? "_LockTask" : ""; + static final String POSTFIX_PAUSE = APPEND_CATEGORY_NAME ? "_Pause" : ""; + static final String POSTFIX_RECENTS = APPEND_CATEGORY_NAME ? "_Recents" : ""; + static final String POSTFIX_SAVED_STATE = APPEND_CATEGORY_NAME ? "_SavedState" : ""; + static final String POSTFIX_STACK = APPEND_CATEGORY_NAME ? "_Stack" : ""; + static final String POSTFIX_STATES = APPEND_CATEGORY_NAME ? "_States" : ""; + static final String POSTFIX_SWITCH = APPEND_CATEGORY_NAME ? "_Switch" : ""; + static final String POSTFIX_TASKS = APPEND_CATEGORY_NAME ? "_Tasks" : ""; + static final String POSTFIX_TRANSITION = APPEND_CATEGORY_NAME ? "_Transition" : ""; + static final String POSTFIX_VISIBILITY = APPEND_CATEGORY_NAME ? "_Visibility" : ""; + static final String POSTFIX_RESULTS = APPEND_CATEGORY_NAME ? "_Results" : ""; +} diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java index b369b7135b4e..6398680b7122 100644 --- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java @@ -40,6 +40,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ApplicationInfo.FLAG_FACTORY_TEST; +import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED; import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS; import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; import static android.content.pm.PackageManager.FEATURE_PC; @@ -67,29 +68,26 @@ import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE; import static android.view.WindowManager.TRANSIT_TASK_OPEN; import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IMMERSIVE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IMMERSIVE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.ActivityManagerService.ANIMATE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_FOCUS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_IMMERSIVE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_IMMERSIVE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityManagerService.MY_PID; -import static com.android.server.am.ActivityManagerService.SEND_LOCALE_TO_MOUNT_DAEMON_MSG; import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS; -import static com.android.server.am.ActivityManagerService.UPDATE_CONFIGURATION_MSG; import static com.android.server.am.ActivityManagerService.dumpStackTraces; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME; @@ -100,7 +98,7 @@ import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG; import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG; -import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; @@ -141,7 +139,7 @@ import android.app.WindowConfiguration; import android.app.admin.DevicePolicyCache; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; -import android.app.usage.UsageEvents; +import android.app.usage.UsageStatsManagerInternal; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.ContentResolver; @@ -179,6 +177,7 @@ import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; import android.os.PowerManager; +import android.os.PowerManagerInternal; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StrictMode; @@ -189,6 +188,8 @@ import android.os.UpdateLock; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; +import android.os.storage.IStorageManager; +import android.os.storage.StorageManager; import android.provider.Settings; import android.service.voice.IVoiceInteractionSession; import android.service.voice.VoiceInteractionManagerInternal; @@ -230,6 +231,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.Watchdog; +import com.android.server.firewall.IntentFirewall; import com.android.server.pm.UserManagerService; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.vr.VrManagerInternal; @@ -254,7 +256,7 @@ import java.util.Locale; * {@hide} */ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM; private static final String TAG_STACK = TAG + POSTFIX_STACK; private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE; @@ -268,12 +270,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // How long we wait until we timeout on key dispatching during instrumentation. private static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000; + /** Used to indicate that an app transition should be animated. */ + static final boolean ANIMATE = true; + + /** Hardware-reported OpenGLES version. */ + final int GL_ES_VERSION; + Context mContext; /** * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can * change at runtime. Use mContext for non-UI purposes. */ final Context mUiContext; + final ActivityThread mSystemThread; H mH; UiHandler mUiHandler; ActivityManagerService mAm; @@ -281,7 +290,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { UriGrantsManagerInternal mUgmInternal; private PackageManagerInternal mPmInternal; private ActivityTaskManagerInternal mInternal; + PowerManagerInternal mPowerManagerInternal; + private UsageStatsManagerInternal mUsageStatsInternal; + PendingIntentController mPendingIntentController; + IntentFirewall mIntentFirewall; + /* Global service lock used by the package the owns this service. */ Object mGlobalLock; ActivityStackSupervisor mStackSupervisor; @@ -536,8 +550,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ActivityTaskManagerService(Context context) { mContext = context; mFactoryTest = FactoryTest.getMode(); - mUiContext = ActivityThread.currentActivityThread().getSystemUiContext(); + mSystemThread = ActivityThread.currentActivityThread(); + mUiContext = mSystemThread.getSystemUiContext(); mLifecycleManager = new ClientLifecycleManager(); + GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED); } void onSystemReady() { @@ -551,6 +567,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { void onInitPowerManagement() { mStackSupervisor.initPowerManagement(); final PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); + mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mVoiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*voice*"); mVoiceWakeLock.setReferenceCounted(false); } @@ -637,15 +654,17 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } // TODO: Will be converted to WM lock once transition is complete. - void setActivityManagerService(ActivityManagerService am) { + void setActivityManagerService(ActivityManagerService am, Looper looper, + IntentFirewall intentFirewall, PendingIntentController intentController) { mAm = am; mGlobalLock = mAm; - mH = new H(mAm.mHandlerThread.getLooper()); + mH = new H(looper); mUiHandler = new UiHandler(); + mIntentFirewall = intentFirewall; final File systemDir = SystemServiceManager.ensureSystemDir(); mAppWarnings = new AppWarnings(this, mUiContext, mH, mUiHandler, systemDir); mCompatModePackages = new CompatModePackages(this, systemDir, mH); - mPendingIntentController = mAm.mPendingIntentController; + mPendingIntentController = intentController; mTempConfig.setToDefaults(); mTempConfig.setLocales(LocaleList.getDefault()); @@ -684,6 +703,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mLockTaskController.setWindowManager(wm); } + void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) { + mUsageStatsInternal = usageStatsManager; + } + UserManagerService getUserManager() { if (mUserManager == null) { IBinder b = ServiceManager.getService(Context.USER_SERVICE); @@ -763,7 +786,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { && globalConfig.keyboard != Configuration.KEYBOARD_NOKEYS) { config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; } - config.reqGlEsVersion = mAm.GL_ES_VERSION; + config.reqGlEsVersion = GL_ES_VERSION; } return config; } @@ -2761,8 +2784,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long origId = Binder.clearCallingIdentity(); try { - WindowProcessController app = - mAm.getRecordForAppLocked(appInt).getWindowProcessController(); + final WindowProcessController app = getProcessController(appInt); mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem"); } finally { Binder.restoreCallingIdentity(origId); @@ -2783,7 +2805,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); if (mKeyguardShown != keyguardShowing) { mKeyguardShown = keyguardShowing; - reportCurKeyguardUsageEventLocked(keyguardShowing); + final Message msg = PooledLambda.obtainMessage( + ActivityManagerInternal::reportCurKeyguardUsageEvent, mAmInternal, + keyguardShowing); + mH.sendMessage(msg); } try { mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing, @@ -2920,12 +2945,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mTaskChangeNotificationController.unregisterTaskStackListener(listener); } - private void reportCurKeyguardUsageEventLocked(boolean keyguardShowing) { - mAm.reportGlobalUsageEventLocked(keyguardShowing - ? UsageEvents.Event.KEYGUARD_SHOWN - : UsageEvents.Event.KEYGUARD_HIDDEN); - } - @Override public boolean requestAssistContextExtras(int requestType, IAssistDataReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId) { @@ -3892,8 +3911,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } if (mWindowManager != null) { - // Update OOM levels based on display size. - mAm.mProcessList.applyDisplaySize(mWindowManager); + final Message msg = PooledLambda.obtainMessage( + ActivityManagerInternal::updateOomLevelsForDisplay, mAmInternal, displayId); + mH.sendMessage(msg); } final long origId = Binder.clearCallingIdentity(); @@ -3921,8 +3941,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } if (mWindowManager != null) { - // Update OOM levels based on display size. - mAm.mProcessList.applyDisplaySize(mWindowManager); + final Message msg = PooledLambda.obtainMessage( + ActivityManagerInternal::updateOomLevelsForDisplay, mAmInternal, + DEFAULT_DISPLAY); + mH.sendMessage(msg); } final long origId = Binder.clearCallingIdentity(); @@ -4129,11 +4151,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public void setVrThread(int tid) { enforceSystemHasVrFeature(); synchronized (mGlobalLock) { - synchronized (mAm.mPidsSelfLocked) { - final int pid = Binder.getCallingPid(); - final ProcessRecord proc = mAm.mPidsSelfLocked.get(pid); - mVrController.setVrThreadLocked(tid, pid, proc.getWindowProcessController()); - } + final int pid = Binder.getCallingPid(); + final WindowProcessController wpc = mPidMap.get(pid); + mVrController.setVrThreadLocked(tid, pid, wpc); } } @@ -4150,11 +4170,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } enforceSystemHasVrFeature(); synchronized (mGlobalLock) { - synchronized (mAm.mPidsSelfLocked) { - final int pid = Binder.getCallingPid(); - final ProcessRecord proc = mAm.mPidsSelfLocked.get(pid); - mVrController.setPersistentVrThreadLocked(tid, pid, proc); - } + final int pid = Binder.getCallingPid(); + final WindowProcessController proc = mPidMap.get(pid); + mVrController.setPersistentVrThreadLocked(tid, pid, proc); } } @@ -4486,8 +4504,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { SystemProperties.set("persist.sys.locale", locales.get(bestLocaleIndex).toLanguageTag()); LocaleList.setDefault(locales, bestLocaleIndex); - mAm.mHandler.sendMessage(mAm.mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG, - locales.get(bestLocaleIndex))); + + final Message m = PooledLambda.obtainMessage( + ActivityTaskManagerService::sendLocaleToMountDaemonMsg, this, + locales.get(bestLocaleIndex)); + mH.sendMessage(m); } mTempConfig.seq = increaseConfigurationSeqLocked(); @@ -4497,8 +4518,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig); // TODO(multi-display): Update UsageEvents#Event to include displayId. - mAm.mUsageStatsService.reportConfigurationChange( - mTempConfig, mAmInternal.getCurrentUserId()); + mUsageStatsInternal.reportConfigurationChange(mTempConfig, mAmInternal.getCurrentUserId()); // TODO: If our config changes, should we auto dismiss any currently showing dialogs? updateShouldShowDialogsLocked(mTempConfig); @@ -4512,16 +4532,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // to retrieve resource values after we return will be sure to get the new ones. This is // especially important during boot, where the first config change needs to guarantee all // resources have that config before following boot code is executed. - mAm.mSystemThread.applyConfigurationToResources(mTempConfig); + mSystemThread.applyConfigurationToResources(mTempConfig); // We need another copy of global config because we're scheduling some calls instead of // running them in place. We need to be sure that object we send will be handled unchanged. final Configuration configCopy = new Configuration(mTempConfig); if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { - Message msg = mAm.mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); - msg.obj = configCopy; - msg.arg1 = userId; - mAm.mHandler.sendMessage(msg); + final Message msg = PooledLambda.obtainMessage( + ActivityTaskManagerService::sendPutConfigurationForUserMsg, + this, userId, configCopy); + mH.sendMessage(msg); } for (int i = mPidMap.size() - 1; i >= 0; i--) { @@ -4659,6 +4679,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mWindowManager.setEventDispatching(booted && !mShuttingDown); } + private void sendPutConfigurationForUserMsg(int userId, Configuration config) { + final ContentResolver resolver = mContext.getContentResolver(); + Settings.System.putConfigurationForUser(resolver, config, userId); + } + + private void sendLocaleToMountDaemonMsg(Locale l) { + try { + IBinder service = ServiceManager.getService("mount"); + IStorageManager storageManager = IStorageManager.Stub.asInterface(service); + Log.d(TAG, "Storing locale " + l.toLanguageTag() + " for decryption UI"); + storageManager.setField(StorageManager.SYSTEM_LOCALE_KEY, l.toLanguageTag()); + } catch (RemoteException e) { + Log.e(TAG, "Error storing locale for decryption UI", e); + } + } + + boolean isActivityStartsLoggingEnabled() { + return mAmInternal.isActivityStartsLoggingEnabled(); + } + void enableScreenAfterBoot(boolean booted) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN, SystemClock.uptimeMillis()); @@ -5266,6 +5306,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mProcessNames.get(processName, uid); } + WindowProcessController getProcessController(IApplicationThread thread) { + if (thread == null) { + return null; + } + + final IBinder threadBinder = thread.asBinder(); + final ArrayMap<String, SparseArray<WindowProcessController>> pmap = mProcessNames.getMap(); + for (int i = pmap.size()-1; i >= 0; i--) { + final SparseArray<WindowProcessController> procs = pmap.valueAt(i); + for (int j = procs.size() - 1; j >= 0; j--) { + final WindowProcessController proc = procs.valueAt(j); + if (proc.hasThread() && proc.getThread().asBinder() == threadBinder) { + return proc; + } + } + } + + return null; + } + void logAppTooSlow(WindowProcessController app, long startTime, String msg) { if (true || Build.IS_USER) { return; @@ -5327,6 +5387,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final class H extends Handler { static final int REPORT_TIME_TRACKER_MSG = 1; + static final int FIRST_ACTIVITY_STACK_MSG = 100; + static final int FIRST_SUPERVISOR_STACK_MSG = 200; public H(Looper looper) { super(looper, null, true); @@ -5971,7 +6033,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mUiHandler.post(() -> { Dialog d = new FactoryErrorDialog(mUiContext, errorMsg); d.show(); - mAm.ensureBootCompleted(); + mAmInternal.ensureBootCompleted(); }); } } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 6a9c8877ce5b..a05fbc695370 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -684,7 +684,7 @@ class AppErrors { Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; final boolean procIsBoundForeground = - (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); + (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); Long crashTime; Long crashTimePersistent; @@ -878,7 +878,7 @@ class AppErrors { // several places in the system server. return app.isInterestingToUserLocked() || (app.info != null && "com.android.systemui".equals(app.info.packageName)) || - (app.hasTopUi || app.hasOverlayUi); + (app.hasTopUi() || app.hasOverlayUi()); } final void appNotResponding(ProcessRecord app, ActivityRecord activity, diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java index 536f3a93a3f1..3c4ab006a4b6 100644 --- a/services/core/java/com/android/server/am/CompatModePackages.java +++ b/services/core/java/com/android/server/am/CompatModePackages.java @@ -16,8 +16,11 @@ package com.android.server.am; -import static com.android.server.am.ActivityManagerDebugConfig.*; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import java.io.File; import java.io.FileInputStream; @@ -48,7 +51,7 @@ import android.util.Slog; import android.util.Xml; public final class CompatModePackages { - private static final String TAG = TAG_WITH_CLASS_NAME ? "CompatModePackages" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "CompatModePackages" : TAG_ATM; private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; private final ActivityTaskManagerService mService; @@ -61,7 +64,7 @@ public final class CompatModePackages { private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>(); - private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG; + private static final int MSG_WRITE = 300; private final CompatHandler mHandler; @@ -321,16 +324,16 @@ public final class CompatModePackages { ActivityRecord starting = stack.restartPackage(packageName); // Tell all processes that loaded this package about the change. - for (int i = mService.mAm.mLruProcesses.size() - 1; i >= 0; i--) { - final ProcessRecord app = mService.mAm.mLruProcesses.get(i); - if (!app.pkgList.containsKey(packageName)) { + for (int i = mService.mPidMap.size() - 1; i >= 0; i--) { + final WindowProcessController app = mService.mPidMap.valueAt(i); + if (!app.mPkgList.contains(packageName)) { continue; } try { - if (app.thread != null) { + if (app.hasThread()) { if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc " - + app.processName + " new compat " + ci); - app.thread.updatePackageCompatibilityInfo(packageName, ci); + + app.mName + " new compat " + ci); + app.getThread().updatePackageCompatibilityInfo(packageName, ci); } } catch (Exception e) { } diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 09c152ef5135..2ca134465cd6 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -56,6 +56,10 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class); sGlobalSettingToTypeMap.put(Settings.Global.ANGLE_ENABLED_APP, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class); + sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class); // add other global settings here... } diff --git a/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java b/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java index e5add58f287a..b39873fe4335 100644 --- a/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java +++ b/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java @@ -16,8 +16,8 @@ package com.android.server.am; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.app.AlertDialog; import android.content.Context; @@ -34,7 +34,7 @@ import com.android.internal.R; import com.android.server.utils.AppInstallerUtil; public class DeprecatedTargetSdkVersionDialog { - private static final String TAG = TAG_WITH_CLASS_NAME ? "DeprecatedTargetSdkVersionDialog" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "DeprecatedTargetSdkVersionDialog" : TAG_ATM; private final AlertDialog mDialog; private final String mPackageName; diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index cfe282917f3b..28b2a42522eb 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -30,9 +30,9 @@ import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES; import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING; import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID; @@ -60,7 +60,7 @@ import java.io.PrintWriter; */ class KeyguardController { - private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM; private final ActivityStackSupervisor mStackSupervisor; private WindowManagerService mWindowManager; diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java index 643c922ad2ca..5b31d5fc593f 100644 --- a/services/core/java/com/android/server/am/LockTaskController.java +++ b/services/core/java/com/android/server/am/LockTaskController.java @@ -28,10 +28,10 @@ import static android.os.UserHandle.USER_CURRENT; import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; @@ -84,7 +84,7 @@ import java.util.Arrays; * @see Activity#stopLockTask() */ public class LockTaskController { - private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_ATM; private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; @VisibleForTesting diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java index a8e1ccca8b9d..98f3f95ebb87 100644 --- a/services/core/java/com/android/server/am/MemoryStatUtil.java +++ b/services/core/java/com/android/server/am/MemoryStatUtil.java @@ -16,7 +16,7 @@ package com.android.server.am; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_METRICS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 3ac7885eba37..9e7ce3204444 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -162,9 +162,11 @@ public final class ProcessList { // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs) // LMK_PROCPRIO <pid> <uid> <prio> // LMK_PROCREMOVE <pid> + // LMK_PROCPURGE static final byte LMK_TARGET = 0; static final byte LMK_PROCPRIO = 1; static final byte LMK_PROCREMOVE = 2; + static final byte LMK_PROCPURGE = 3; // These are the various interesting memory levels that we will give to // the OOM killer. Note that the OOM killer only supports 6 slots, so we @@ -813,31 +815,46 @@ public final class ProcessList { return true; } + // Never call directly, use writeLmkd() instead + private static boolean writeLmkdCommand(ByteBuffer buf) { + try { + sLmkdOutputStream.write(buf.array(), 0, buf.position()); + } catch (IOException ex) { + Slog.w(TAG, "Error writing to lowmemorykiller socket"); + + try { + sLmkdSocket.close(); + } catch (IOException ex2) { + } + + sLmkdSocket = null; + return false; + } + return true; + } + private static void writeLmkd(ByteBuffer buf) { for (int i = 0; i < 3; i++) { if (sLmkdSocket == null) { - if (openLmkdSocket() == false) { - try { - Thread.sleep(1000); - } catch (InterruptedException ie) { - } - continue; + if (openLmkdSocket() == false) { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { } - } - - try { - sLmkdOutputStream.write(buf.array(), 0, buf.position()); - return; - } catch (IOException ex) { - Slog.w(TAG, "Error writing to lowmemorykiller socket"); - - try { - sLmkdSocket.close(); - } catch (IOException ex2) { + continue; } - sLmkdSocket = null; + // Purge any previously registered pids + ByteBuffer purge_buf = ByteBuffer.allocate(4); + purge_buf.putInt(LMK_PROCPURGE); + if (writeLmkdCommand(purge_buf) == false) { + // Write failed, skip the rest and retry + continue; + } + } + if (writeLmkdCommand(buf)) { + return; } } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 667d3faefc9f..3128333def6f 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -136,7 +136,7 @@ final class ProcessRecord implements WindowProcessListener { private int mCurSchedGroup; // Currently desired scheduling class int setSchedGroup; // Last set to background scheduling class int trimMemoryLevel; // Last selected memory trimming level - int curProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state + private int mCurProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state private int mRepProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for @@ -146,19 +146,19 @@ final class ProcessRecord implements WindowProcessListener { boolean serviceb; // Process currently is on the service B list boolean serviceHighRam; // We are forcing to service B list due to its RAM use boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle? - boolean hasClientActivities; // Are there any client services with activities? + private boolean mHasClientActivities; // Are there any client services with activities? boolean hasStartedServices; // Are there any started services running in this process? private boolean mHasForegroundServices; // Running any services that are foreground? - boolean foregroundActivities; // Running any activities that are foreground? + private boolean mHasForegroundActivities; // Running any activities that are foreground? boolean repForegroundActivities; // Last reported foreground activities. boolean systemNoUi; // This is a system process, but not currently showing UI. boolean hasShownUi; // Has UI been shown in this process since it was started? - boolean hasTopUi; // Is this process currently showing a non-activity UI that the user + private boolean mHasTopUi; // Is this process currently showing a non-activity UI that the user // is interacting with? E.g. The status bar when it is expanded, but // not when it is minimized. When true the // process will be set to use the ProcessList#SCHED_GROUP_TOP_APP // scheduling group to boost performance. - boolean hasOverlayUi; // Is the process currently showing a non-activity UI that + private boolean mHasOverlayUi; // Is the process currently showing a non-activity UI that // overlays on-top of activity UIs on screen. E.g. display a window // of type // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY @@ -171,7 +171,7 @@ final class ProcessRecord implements WindowProcessListener { // performance, as well as oom adj score will be set to // ProcessList#VISIBLE_APP_ADJ at minimum to reduce the chance // of the process getting killed. - boolean pendingUiClean; // Want to clean up resources from showing UI? + private boolean mPendingUiClean; // Want to clean up resources from showing UI? boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower boolean treatLikeActivity; // Bound using BIND_TREAT_LIKE_ACTIVITY boolean bad; // True if disabled in the bad process list @@ -180,8 +180,8 @@ final class ProcessRecord implements WindowProcessListener { boolean procStateChanged; // Keep track of whether we changed 'setAdj'. boolean reportedInteraction;// Whether we have told usage stats about it being an interaction boolean unlocked; // True when proc was started in user unlocked state - long interactionEventTime; // The time we sent the last interaction event - long fgInteractionTime; // When we became foreground for interaction purposes + private long mInteractionEventTime; // The time we sent the last interaction event + private long mFgInteractionTime; // When we became foreground for interaction purposes String waitingToKill; // Process is waiting to be killed when in the bg, and reason Object forcingToImportant; // Token that is forcing this process to be important int adjSeq; // Sequence id for identifying oom_adj assignment cycles @@ -194,7 +194,7 @@ final class ProcessRecord implements WindowProcessListener { // process. private boolean mUsingWrapper; // Set to true when process was launched with a wrapper attached final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app - long whenUnimportant; // When (uptime) the process last became unimportant + private long mWhenUnimportant; // When (uptime) the process last became unimportant long lastCpuTime; // How long proc has run CPU at last check long curCpuTime; // How long proc has run CPU most recently long lastRequestedGc; // When we last asked the app to do a gc @@ -370,38 +370,38 @@ final class ProcessRecord implements WindowProcessListener { pw.print(" setSchedGroup="); pw.print(setSchedGroup); pw.print(" systemNoUi="); pw.print(systemNoUi); pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel); - pw.print(prefix); pw.print("curProcState="); pw.print(curProcState); + pw.print(prefix); pw.print("curProcState="); pw.print(getCurProcState()); pw.print(" mRepProcState="); pw.print(mRepProcState); pw.print(" pssProcState="); pw.print(pssProcState); pw.print(" setProcState="); pw.print(setProcState); pw.print(" lastStateTime="); TimeUtils.formatDuration(lastStateTime, nowUptime, pw); pw.println(); - if (hasShownUi || pendingUiClean || hasAboveClient || treatLikeActivity) { + if (hasShownUi || mPendingUiClean || hasAboveClient || treatLikeActivity) { pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi); - pw.print(" pendingUiClean="); pw.print(pendingUiClean); + pw.print(" pendingUiClean="); pw.print(mPendingUiClean); pw.print(" hasAboveClient="); pw.print(hasAboveClient); pw.print(" treatLikeActivity="); pw.println(treatLikeActivity); } - if (hasTopUi || hasOverlayUi || runningRemoteAnimation) { - pw.print(prefix); pw.print("hasTopUi="); pw.print(hasTopUi); - pw.print(" hasOverlayUi="); pw.print(hasOverlayUi); + if (hasTopUi() || hasOverlayUi() || runningRemoteAnimation) { + pw.print(prefix); pw.print("hasTopUi="); pw.print(hasTopUi()); + pw.print(" hasOverlayUi="); pw.print(hasOverlayUi()); pw.print(" runningRemoteAnimation="); pw.println(runningRemoteAnimation); } if (mHasForegroundServices || forcingToImportant != null) { pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices); pw.print(" forcingToImportant="); pw.println(forcingToImportant); } - if (reportedInteraction || fgInteractionTime != 0) { + if (reportedInteraction || mFgInteractionTime != 0) { pw.print(prefix); pw.print("reportedInteraction="); pw.print(reportedInteraction); - if (interactionEventTime != 0) { + if (mInteractionEventTime != 0) { pw.print(" time="); - TimeUtils.formatDuration(interactionEventTime, SystemClock.elapsedRealtime(), pw); + TimeUtils.formatDuration(mInteractionEventTime, SystemClock.elapsedRealtime(), pw); } - if (fgInteractionTime != 0) { + if (mFgInteractionTime != 0) { pw.print(" fgInteractionTime="); - TimeUtils.formatDuration(fgInteractionTime, SystemClock.elapsedRealtime(), pw); + TimeUtils.formatDuration(mFgInteractionTime, SystemClock.elapsedRealtime(), pw); } pw.println(); } @@ -409,9 +409,9 @@ final class ProcessRecord implements WindowProcessListener { pw.print(prefix); pw.print("persistent="); pw.print(mPersistent); pw.print(" removed="); pw.println(removed); } - if (hasClientActivities || foregroundActivities || repForegroundActivities) { - pw.print(prefix); pw.print("hasClientActivities="); pw.print(hasClientActivities); - pw.print(" foregroundActivities="); pw.print(foregroundActivities); + if (mHasClientActivities || mHasForegroundActivities || repForegroundActivities) { + pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities); + pw.print(" foregroundActivities="); pw.print(mHasForegroundActivities); pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")"); } if (lastProviderTime > 0) { @@ -438,7 +438,7 @@ final class ProcessRecord implements WindowProcessListener { TimeUtils.formatDuration(curCpuTime - lastCpuTime, pw); } pw.print(" whenUnimportant="); - TimeUtils.formatDuration(whenUnimportant - nowUptime, pw); + TimeUtils.formatDuration(mWhenUnimportant - nowUptime, pw); pw.println(); } pw.print(prefix); pw.print("lastRequestedGc="); @@ -857,7 +857,8 @@ final class ProcessRecord implements WindowProcessListener { public void forceProcessStateUpTo(int newState) { if (mRepProcState > newState) { - curProcState = mRepProcState = newState; + mRepProcState = newState; + setCurProcState(newState); for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), @@ -931,6 +932,15 @@ final class ProcessRecord implements WindowProcessListener { return mCurSchedGroup; } + void setCurProcState(int curProcState) { + mCurProcState = curProcState; + mWindowProcessController.setCurrentProcState(mCurProcState); + } + + int getCurProcState() { + return mCurProcState; + } + void setReportedProcState(int repProcState) { mRepProcState = repProcState; for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { @@ -991,6 +1001,69 @@ final class ProcessRecord implements WindowProcessListener { return mHasForegroundServices; } + void setHasForegroundActivities(boolean hasForegroundActivities) { + mHasForegroundActivities = hasForegroundActivities; + mWindowProcessController.setHasForegroundActivities(hasForegroundActivities); + } + + boolean hasForegroundActivities() { + return mHasForegroundActivities; + } + + void setHasClientActivities(boolean hasClientActivities) { + mHasClientActivities = hasClientActivities; + mWindowProcessController.setHasClientActivities(hasClientActivities); + } + + boolean hasClientActivities() { + return mHasClientActivities; + } + + void setHasTopUi(boolean hasTopUi) { + mHasTopUi = hasTopUi; + mWindowProcessController.setHasTopUi(hasTopUi); + } + + boolean hasTopUi() { + return mHasTopUi; + } + + void setHasOverlayUi(boolean hasOverlayUi) { + mHasOverlayUi = hasOverlayUi; + mWindowProcessController.setHasOverlayUi(hasOverlayUi); + } + + boolean hasOverlayUi() { + return mHasOverlayUi; + } + + void setInteractionEventTime(long interactionEventTime) { + mInteractionEventTime = interactionEventTime; + mWindowProcessController.setInteractionEventTime(interactionEventTime); + } + + long getInteractionEventTime() { + return mInteractionEventTime; + } + + void setFgInteractionTime(long fgInteractionTime) { + mFgInteractionTime = fgInteractionTime; + mWindowProcessController.setFgInteractionTime(fgInteractionTime); + } + + long getFgInteractionTime() { + return mFgInteractionTime; + } + + void setWhenUnimportant(long whenUnimportant) { + mWhenUnimportant = whenUnimportant; + mWindowProcessController.setWhenUnimportant(whenUnimportant); + } + + long getWhenUnimportant() { + return mWhenUnimportant; + } + void setDebugging(boolean debugging) { mDebugging = debugging; mWindowProcessController.setDebugging(debugging); @@ -1039,14 +1112,19 @@ final class ProcessRecord implements WindowProcessListener { @Override public void setPendingUiClean(boolean pendingUiClean) { synchronized (mService) { - this.pendingUiClean = true; + mPendingUiClean = pendingUiClean; + mWindowProcessController.setPendingUiClean(pendingUiClean); } } + boolean hasPendingUiClean() { + return mPendingUiClean; + } + @Override public void setPendingUiCleanAndForceProcessStateUpTo(int newState) { synchronized (mService) { - pendingUiClean = true; + setPendingUiClean(true); forceProcessStateUpTo(newState); } } diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java index dd13e9868b1d..57f939f4438b 100644 --- a/services/core/java/com/android/server/am/RecentTasks.java +++ b/services/core/java/com/android/server/am/RecentTasks.java @@ -33,15 +33,15 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.Process.SYSTEM_UID; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; -import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -103,7 +103,7 @@ import java.util.concurrent.TimeUnit; * // 'X' tasks are trimmed. */ class RecentTasks { - private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_ATM; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; private static final String TAG_TASKS = TAG + POSTFIX_TASKS; diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java index fa0cb47ade02..115216592e71 100644 --- a/services/core/java/com/android/server/am/SafeActivityOptions.java +++ b/services/core/java/com/android/server/am/SafeActivityOptions.java @@ -21,9 +21,9 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.Display.INVALID_DISPLAY; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.annotation.Nullable; import android.app.ActivityOptions; @@ -46,7 +46,7 @@ import com.android.internal.annotations.VisibleForTesting; */ public class SafeActivityOptions { - private static final String TAG = TAG_WITH_CLASS_NAME ? "SafeActivityOptions" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "SafeActivityOptions" : TAG_ATM; private final int mOriginalCallingPid; private final int mOriginalCallingUid; diff --git a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java index 04f4facfbf15..eae28127a67f 100644 --- a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java @@ -35,8 +35,8 @@ import static android.util.DisplayMetrics.DENSITY_DEFAULT; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.annotation.NonNull; import android.annotation.Nullable; @@ -59,7 +59,7 @@ import java.util.List; * The class that defines the default launch params for tasks. */ class TaskLaunchParamsModifier implements LaunchParamsModifier { - private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_ATM; private static final boolean DEBUG = false; // A mask for SUPPORTS_SCREEN that indicates the activity supports resize. diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 05b0d598f878..5f5916331e67 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -17,6 +17,7 @@ package com.android.server.am; import static android.app.ActivityTaskManager.INVALID_STACK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED; import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; @@ -45,16 +46,16 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VER import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP; @@ -129,7 +130,7 @@ import java.util.Objects; // TODO: Make package private again once move to WM package is complete. public class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener { - private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; @@ -172,7 +173,6 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont // code. private static final int PERSIST_TASK_VERSION = 1; - static final int INVALID_TASK_ID = -1; private static final int INVALID_MIN_SIZE = -1; /** diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java index 366f95a170ff..51d86d66e6c1 100644 --- a/services/core/java/com/android/server/am/VrController.java +++ b/services/core/java/com/android/server/am/VrController.java @@ -248,9 +248,9 @@ final class VrController { * * @param tid the tid of the thread to set, or 0 to unset the current thread. * @param pid the pid of the process owning the thread to set. - * @param proc the ProcessRecord of the process owning the thread to set. + * @param proc the process owning the thread to set. */ - public void setPersistentVrThreadLocked(int tid, int pid, ProcessRecord proc) { + public void setPersistentVrThreadLocked(int tid, int pid, WindowProcessController proc) { if (!hasPersistentVrFlagSet()) { Slog.w(TAG, "Persistent VR thread may only be set in persistent VR mode!"); return; diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java index f6f4db6a2d37..a461d1c4b849 100644 --- a/services/core/java/com/android/server/am/WindowProcessController.java +++ b/services/core/java/com/android/server/am/WindowProcessController.java @@ -18,12 +18,12 @@ package com.android.server.am; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; -import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; +import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStack.ActivityState.DESTROYED; import static com.android.server.am.ActivityStack.ActivityState.DESTROYING; import static com.android.server.am.ActivityStack.ActivityState.PAUSED; @@ -63,7 +63,7 @@ import java.util.ArrayList; * calls are allowed to proceed. */ public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer> { - private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_AM; + private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM; private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; @@ -87,6 +87,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio private volatile IApplicationThread mThread; // Currently desired scheduling class private volatile int mCurSchedGroup; + // Currently computed process state + private volatile int mCurProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state; private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT; // are we in the process of crashing? @@ -99,6 +101,28 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio private volatile String mRequiredAbi; // Running any services that are foreground? private volatile boolean mHasForegroundServices; + // Running any activities that are foreground? + private volatile boolean mHasForegroundActivities; + // Are there any client services with activities? + private volatile boolean mHasClientActivities; + // Is this process currently showing a non-activity UI that the user is interacting with? + // E.g. The status bar when it is expanded, but not when it is minimized. When true the process + // will be set to use the ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost performance. + private volatile boolean mHasTopUi; + // Is the process currently showing a non-activity UI that overlays on-top of activity UIs on + // screen. E.g. display a window of type + // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY When true the process will + // oom adj score will be set to ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance + // of the process getting killed. + private volatile boolean mHasOverlayUi; + // Want to clean up resources from showing UI? + private volatile boolean mPendingUiClean; + // The time we sent the last interaction event + private volatile long mInteractionEventTime; + // When we became foreground for interaction purposes + private volatile long mFgInteractionTime; + // When (uptime) the process last became unimportant + private volatile long mWhenUnimportant; // was app launched for debugging? private volatile boolean mDebugging; // Active instrumentation running in process? @@ -161,6 +185,14 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return mCurSchedGroup; } + public void setCurrentProcState(int curProcState) { + mCurProcState = curProcState; + } + + int getCurrentProcState() { + return mCurProcState; + } + public void setReportedProcState(int repProcState) { mRepProcState = repProcState; } @@ -201,6 +233,78 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return mHasForegroundServices; } + public void setHasForegroundActivities(boolean hasForegroundActivities) { + mHasForegroundActivities = hasForegroundActivities; + } + + boolean hasForegroundActivities() { + return mHasForegroundActivities; + } + + public void setHasClientActivities(boolean hasClientActivities) { + mHasClientActivities = hasClientActivities; + } + + boolean hasClientActivities() { + return mHasClientActivities; + } + + public void setHasTopUi(boolean hasTopUi) { + mHasTopUi = hasTopUi; + } + + boolean hasTopUi() { + return mHasTopUi; + } + + public void setHasOverlayUi(boolean hasOverlayUi) { + mHasOverlayUi = hasOverlayUi; + } + + boolean hasOverlayUi() { + return mHasOverlayUi; + } + + public void setPendingUiClean(boolean hasPendingUiClean) { + mPendingUiClean = hasPendingUiClean; + } + + boolean hasPendingUiClean() { + return mPendingUiClean; + } + + void postPendingUiCleanMsg(boolean pendingUiClean) { + if (mListener == null) return; + // Posting on handler so WM lock isn't held when we call into AM. + final Message m = PooledLambda.obtainMessage( + WindowProcessListener::setPendingUiClean, mListener, pendingUiClean); + mAtm.mH.sendMessage(m); + } + + public void setInteractionEventTime(long interactionEventTime) { + mInteractionEventTime = interactionEventTime; + } + + long getInteractionEventTime() { + return mInteractionEventTime; + } + + public void setFgInteractionTime(long fgInteractionTime) { + mFgInteractionTime = fgInteractionTime; + } + + long getFgInteractionTime() { + return mFgInteractionTime; + } + + public void setWhenUnimportant(long whenUnimportant) { + mWhenUnimportant = whenUnimportant; + } + + long getWhenUnimportant() { + return mWhenUnimportant; + } + public void setRequiredAbi(String requiredAbi) { mRequiredAbi = requiredAbi; } @@ -532,14 +636,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio WindowProcessListener::updateServiceConnectionActivities, mListener)); } - void setPendingUiClean(boolean pendingUiClean) { - if (mListener == null) return; - // Posting on handler so WM lock isn't held when we call into AM. - final Message m = PooledLambda.obtainMessage( - WindowProcessListener::setPendingUiClean, mListener, pendingUiClean); - mAtm.mH.sendMessage(m); - } - void setPendingUiCleanAndForceProcessStateUpTo(int newState) { if (mListener == null) return; // Posting on handler so WM lock isn't held when we call into AM. diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java index 47e85b5fd3ab..15468ff05c08 100644 --- a/services/core/java/com/android/server/connectivity/ProxyTracker.java +++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java @@ -126,9 +126,9 @@ public class ProxyTracker { public ProxyInfo getDefaultProxy() { // This information is already available as a world read/writable jvm property. synchronized (mProxyLock) { - final ProxyInfo ret = mGlobalProxy; - if ((ret == null) && mDefaultProxyEnabled) return mDefaultProxy; - return ret; + if (mGlobalProxy != null) return mGlobalProxy; + if (mDefaultProxyEnabled) return mDefaultProxy; + return null; } } @@ -204,11 +204,10 @@ public class ProxyTracker { * * Confusingly this method also sets the PAC file URL. TODO : separate this, it has nothing * to do in a "sendProxyBroadcast" method. - * @param proxyInfo the proxy spec, or null for no proxy. */ - // TODO : make the argument NonNull final and the method private - public void sendProxyBroadcast(@Nullable ProxyInfo proxyInfo) { - if (proxyInfo == null) proxyInfo = new ProxyInfo("", 0, ""); + public void sendProxyBroadcast() { + final ProxyInfo defaultProxy = getDefaultProxy(); + final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, ""); if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)) return; if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo); Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); @@ -269,7 +268,7 @@ public class ProxyTracker { Binder.restoreCallingIdentity(token); } - sendProxyBroadcast(mGlobalProxy == null ? mDefaultProxy : proxyInfo); + sendProxyBroadcast(); } } @@ -296,14 +295,14 @@ public class ProxyTracker { && (!Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) && proxyInfo.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) { mGlobalProxy = proxyInfo; - sendProxyBroadcast(mGlobalProxy); + sendProxyBroadcast(); return; } mDefaultProxy = proxyInfo; if (mGlobalProxy != null) return; if (mDefaultProxyEnabled) { - sendProxyBroadcast(proxyInfo); + sendProxyBroadcast(); } } } @@ -320,7 +319,7 @@ public class ProxyTracker { if (mDefaultProxyEnabled != enabled) { mDefaultProxyEnabled = enabled; if (mGlobalProxy == null && mDefaultProxy != null) { - sendProxyBroadcast(enabled ? mDefaultProxy : null); + sendProxyBroadcast(); } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index a9b0d5c42f73..991ecb8ea3dd 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -421,6 +421,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final IInputContext inputContext; final int uid; final int pid; + final int selfReportedDisplayId; final InputBinding binding; final ClientDeathRecipient clientDeathRecipient; @@ -430,16 +431,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override public String toString() { return "ClientState{" + Integer.toHexString( - System.identityHashCode(this)) + " uid " + uid - + " pid " + pid + "}"; + System.identityHashCode(this)) + " uid=" + uid + + " pid=" + pid + " displayId=" + selfReportedDisplayId + "}"; } ClientState(IInputMethodClient _client, IInputContext _inputContext, - int _uid, int _pid, ClientDeathRecipient _clientDeathRecipient) { + int _uid, int _pid, int _selfReportedDisplayId, + ClientDeathRecipient _clientDeathRecipient) { client = _client; inputContext = _inputContext; uid = _uid; pid = _pid; + selfReportedDisplayId = _selfReportedDisplayId; binding = new InputBinding(null, inputContext.asBinder(), uid, pid); clientDeathRecipient = _clientDeathRecipient; } @@ -1745,15 +1748,21 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * process * @param inputContext communication channel for the dummy * {@link android.view.inputmethod.InputConnection} + * @param selfReportedDisplayId self-reported display ID to which the client is associated. + * Whether the client is still allowed to access to this display + * or not needs to be evaluated every time the client interacts + * with the display */ @Override - public void addClient(IInputMethodClient client, IInputContext inputContext) { + public void addClient(IInputMethodClient client, IInputContext inputContext, + int selfReportedDisplayId) { final int callerUid = Binder.getCallingUid(); final int callerPid = Binder.getCallingPid(); synchronized (mMethodMap) { // TODO: Optimize this linear search. for (ClientState state : mClients.values()) { - if (state.uid == callerUid && state.pid == callerPid) { + if (state.uid == callerUid && state.pid == callerPid + && state.selfReportedDisplayId == selfReportedDisplayId) { throw new SecurityException("uid=" + callerUid + "/pid=" + callerPid + " is already registered"); } @@ -1764,8 +1773,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } catch (RemoteException e) { throw new IllegalStateException(e); } - mClients.put(client.asBinder(), - new ClientState(client, inputContext, callerUid, callerPid, deathRecipient)); + // We cannot fully avoid race conditions where the client UID already lost the access to + // the given self-reported display ID, even if the client is not maliciously reporting + // a fake display ID. Unconditionally returning SecurityException just because the + // client doesn't pass display ID verification can cause many test failures hence not an + // option right now. At the same time + // context.getSystemService(InputMethodManager.class) + // is expected to return a valid non-null instance at any time if we do not choose to + // have the client crash. Thus we do not verify the display ID at all here. Instead we + // later check the display ID every time the client needs to interact with the specified + // display. + mClients.put(client.asBinder(), new ClientState(client, inputContext, callerUid, + callerPid, selfReportedDisplayId, deathRecipient)); } } @@ -1918,8 +1937,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurAttribute = attribute; // Check if the input method is changing. - final int displayId = mWindowManagerInternal.getDisplayIdForWindow( - mCurFocusedWindow); + // We expect the caller has already verified that the client is allowed to access this + // display ID. + final int displayId = mCurFocusedWindowClient.selfReportedDisplayId; if (mCurId != null && mCurId.equals(mCurMethodId) && displayId == mCurTokenDisplayId) { if (cs.curSession != null) { // Fast case: if we are already connected to the input method, @@ -1984,8 +2004,21 @@ public class InputMethodManagerService extends IInputMethodManager.Stub com.android.internal.R.string.input_method_binding_label); mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0)); - final int displayId = mWindowManagerInternal.getDisplayIdForWindow(mCurFocusedWindow); - mCurTokenDisplayId = (displayId != INVALID_DISPLAY) ? displayId : DEFAULT_DISPLAY; + + if (mCurFocusedWindowClient == null) { + // This can happen when called from systemRunning() or switchUserLocked(). In this case, + // there really isn't an actual client yet. Let IME be on the default display. + // TODO(Bug 117730713): Check if really need to bind to the IME or not. + mCurTokenDisplayId = DEFAULT_DISPLAY; + } else { + if (!mWindowManagerInternal.isUidAllowedOnDisplay( + mCurFocusedWindowClient.selfReportedDisplayId, mCurFocusedWindowClient.uid)) { + // Wait, the client no longer has access to the display. + return InputBindResult.INVALID_DISPLAY_ID; + } + final int displayId = mCurFocusedWindowClient.selfReportedDisplayId; + mCurTokenDisplayId = (displayId != INVALID_DISPLAY) ? displayId : DEFAULT_DISPLAY; + } if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) { mLastBindTime = SystemClock.uptimeMillis(); @@ -2584,7 +2617,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (cs == null) { throw new IllegalArgumentException("unknown client " + client.asBinder()); } - if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) { + if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid, + cs.selfReportedDisplayId)) { Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client); return false; } @@ -2668,7 +2702,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (cs == null) { throw new IllegalArgumentException("unknown client " + client.asBinder()); } - if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) { + if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid, + cs.selfReportedDisplayId)) { if (DEBUG) { Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client); } @@ -2767,6 +2802,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub InputBindResult res = null; long ident = Binder.clearCallingIdentity(); try { + final int windowDisplayId = + mWindowManagerInternal.getDisplayIdForWindow(windowToken); synchronized (mMethodMap) { if (DEBUG) Slog.v(TAG, "startInputOrWindowGainedFocusInternal: reason=" + InputMethodClient.getStartInputReason(startInputReason) @@ -2785,8 +2822,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub throw new IllegalArgumentException("unknown client " + client.asBinder()); } + if (cs.selfReportedDisplayId != windowDisplayId) { + Slog.e(TAG, "startInputOrWindowGainedFocusInternal: display ID mismatch." + + " from client:" + cs.selfReportedDisplayId + + " from window:" + windowDisplayId); + return InputBindResult.DISPLAY_ID_MISMATCH; + } - if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) { + if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid, + cs.selfReportedDisplayId)) { // Check with the window manager to make sure this client actually // has a window with focus. If not, reject. This is thread safe // because if the focus changes some time before or after, the @@ -2858,9 +2902,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // If focused display changed, we should unbind current method // to make app window in previous display relayout after Ime // window token removed. - final int newFocusDisplayId = - mWindowManagerInternal.getDisplayIdForWindow(windowToken); - if (newFocusDisplayId != mCurTokenDisplayId) { + // Note that we can trust client's display ID as long as it matches + // to the display ID obtained from the window. + if (cs.selfReportedDisplayId != mCurTokenDisplayId) { unbindCurrentMethodLocked(); } } @@ -2958,6 +3002,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } private boolean canShowInputMethodPickerLocked(IInputMethodClient client) { + // TODO(yukawa): multi-display support. final int uid = Binder.getCallingUid(); if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) { return true; @@ -3034,6 +3079,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override public void showInputMethodAndSubtypeEnablerFromClient( IInputMethodClient client, String inputMethodId) { + // TODO(yukawa): Should we verify the display ID? if (!calledFromValidUser()) { return; } @@ -3229,6 +3275,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ @Override public int getInputMethodWindowVisibleHeight() { + // TODO(yukawa): Should we verify the display ID? return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId); } diff --git a/services/core/java/com/android/server/media/MediaUpdateService.java b/services/core/java/com/android/server/media/MediaUpdateService.java index af06d157a526..7304f0788a1d 100644 --- a/services/core/java/com/android/server/media/MediaUpdateService.java +++ b/services/core/java/com/android/server/media/MediaUpdateService.java @@ -22,7 +22,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.media.IMediaExtractorUpdateService; +import android.media.IMediaUpdateService; import android.os.Build; import android.os.IBinder; import android.os.Handler; @@ -34,6 +34,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Slog; import com.android.server.SystemService; +import java.util.HashMap; /** This class provides a system service that manages media framework updates. */ public class MediaUpdateService extends SystemService { @@ -42,34 +43,40 @@ public class MediaUpdateService extends SystemService { private static final String MEDIA_UPDATE_PACKAGE_NAME = SystemProperties.get("ro.mediacomponents.package"); private static final String EXTRACTOR_UPDATE_SERVICE_NAME = "media.extractor.update"; - - private IMediaExtractorUpdateService mMediaExtractorUpdateService; - final Handler mHandler; + private static final String CODEC_UPDATE_SERVICE_NAME = "media.codec.update"; + private static final String[] UPDATE_SERVICE_NAME_ARRAY = { + EXTRACTOR_UPDATE_SERVICE_NAME, CODEC_UPDATE_SERVICE_NAME, + }; + private final HashMap<String, IMediaUpdateService> mUpdateServiceMap = new HashMap<>(); + private final Handler mHandler = new Handler(); public MediaUpdateService(Context context) { super(context); - mHandler = new Handler(); } @Override public void onStart() { if (("userdebug".equals(android.os.Build.TYPE) || "eng".equals(android.os.Build.TYPE)) && !TextUtils.isEmpty(MEDIA_UPDATE_PACKAGE_NAME)) { - connect(); + for (String serviceName : UPDATE_SERVICE_NAME_ARRAY) { + connect(serviceName); + } registerBroadcastReceiver(); } } - private void connect() { - IBinder binder = ServiceManager.getService(EXTRACTOR_UPDATE_SERVICE_NAME); + private void connect(final String serviceName) { + IBinder binder = ServiceManager.getService(serviceName); if (binder != null) { try { binder.linkToDeath(new IBinder.DeathRecipient() { @Override public void binderDied() { - Slog.w(TAG, "mediaextractor died; reconnecting"); - mMediaExtractorUpdateService = null; - connect(); + Slog.w(TAG, "service " + serviceName + " died; reconnecting"); + synchronized (mUpdateServiceMap) { + mUpdateServiceMap.remove(serviceName); + } + connect(serviceName); } }, 0); } catch (Exception e) { @@ -77,15 +84,18 @@ public class MediaUpdateService extends SystemService { } } if (binder != null) { - mMediaExtractorUpdateService = IMediaExtractorUpdateService.Stub.asInterface(binder); + synchronized (mUpdateServiceMap) { + mUpdateServiceMap.put(serviceName, + IMediaUpdateService.Stub.asInterface(binder)); + } mHandler.post(new Runnable() { @Override public void run() { - packageStateChanged(); + packageStateChanged(serviceName); } }); } else { - Slog.w(TAG, EXTRACTOR_UPDATE_SERVICE_NAME + " not found."); + Slog.w(TAG, serviceName + " not found."); } } @@ -106,13 +116,12 @@ public class MediaUpdateService extends SystemService { // following ACTION_PACKAGE_ADDED case. return; } - packageStateChanged(); - break; + // fall-thru case Intent.ACTION_PACKAGE_CHANGED: - packageStateChanged(); - break; case Intent.ACTION_PACKAGE_ADDED: - packageStateChanged(); + for (String serviceName : UPDATE_SERVICE_NAME_ARRAY) { + packageStateChanged(serviceName); + } break; } } @@ -128,7 +137,7 @@ public class MediaUpdateService extends SystemService { null /* broadcast permission */, null /* handler */); } - private void packageStateChanged() { + private void packageStateChanged(String serviceName) { ApplicationInfo packageInfo = null; boolean pluginsAvailable = false; try { @@ -144,17 +153,23 @@ public class MediaUpdateService extends SystemService { + " targetSdk:" + packageInfo.targetSdkVersion); pluginsAvailable = false; } - loadExtractorPlugins( + loadPlugins(serviceName, (packageInfo != null && pluginsAvailable) ? packageInfo.sourceDir : ""); } - private void loadExtractorPlugins(String apkPath) { + private void loadPlugins(String serviceName, String apkPath) { try { - if (mMediaExtractorUpdateService != null) { - mMediaExtractorUpdateService.loadPlugins(apkPath); + IMediaUpdateService service = null; + synchronized (serviceName) { + service = mUpdateServiceMap.get(serviceName); + } + if (service != null) { + service.loadPlugins(apkPath); + } else { + Slog.w(TAG, "service " + serviceName + " passed away"); } } catch (Exception e) { - Slog.w(TAG, "Error in loadPlugins", e); + Slog.w(TAG, "Error in loadPlugins for " + serviceName, e); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 3528b86b05f4..1180af87ae34 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -188,6 +188,7 @@ import android.content.pm.SELinuxUtil; import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; @@ -12716,8 +12717,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended, - PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage, - String callingPackage, int userId) { + PersistableBundle appExtras, PersistableBundle launcherExtras, + SuspendDialogInfo dialogInfo, String callingPackage, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS, "setPackagesSuspendedAsUser"); @@ -12762,7 +12763,7 @@ public class PackageManagerService extends IPackageManager.Stub unactionedPackages.add(packageName); continue; } - pkgSetting.setSuspended(suspended, callingPackage, dialogMessage, appExtras, + pkgSetting.setSuspended(suspended, callingPackage, dialogInfo, appExtras, launcherExtras, userId); changedPackagesList.add(packageName); changedUids.add(UserHandle.getUid(userId, pkgSetting.appId)); @@ -17816,7 +17817,7 @@ public class PackageManagerService extends IPackageManager.Stub false /*hidden*/, false /*suspended*/, null /*suspendingPackage*/, - null /*dialogMessage*/, + null /*dialogInfo*/, null /*suspendedAppExtras*/, null /*suspendedLauncherExtras*/, false /*instantApp*/, @@ -22585,10 +22586,10 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public String getSuspendedDialogMessage(String suspendedPackage, int userId) { + public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId) { synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(suspendedPackage); - return (ps != null) ? ps.readUserState(userId).dialogMessage : null; + return (ps != null) ? ps.readUserState(userId).dialogInfo : null; } } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 93729d1949b0..e25cca43e8da 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -51,6 +51,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; @@ -1701,9 +1702,18 @@ class PackageManagerShellCommand extends ShellCommand { } final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell"; + + final SuspendDialogInfo info; + if (!TextUtils.isEmpty(dialogMessage)) { + info = new SuspendDialogInfo.Builder() + .setMessage(dialogMessage) + .build(); + } else { + info = null; + } try { mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState, - appExtras, launcherExtras, dialogMessage, callingPackage, userId); + appExtras, launcherExtras, info, callingPackage, userId); pw.println("Package " + packageName + " new suspended state: " + mInterface.isPackageSuspendedForUser(packageName, userId)); return 0; diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index fd6aceb1ce6b..3c22f07ad108 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -26,6 +26,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; import android.content.pm.Signature; +import android.content.pm.SuspendDialogInfo; import android.os.PersistableBundle; import android.service.pm.PackageProto; import android.util.ArraySet; @@ -395,12 +396,12 @@ public abstract class PackageSettingBase extends SettingBase { return readUserState(userId).suspended; } - void setSuspended(boolean suspended, String suspendingPackage, String dialogMessage, + void setSuspended(boolean suspended, String suspendingPackage, SuspendDialogInfo dialogInfo, PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) { final PackageUserState existingUserState = modifyUserState(userId); existingUserState.suspended = suspended; existingUserState.suspendingPackage = suspended ? suspendingPackage : null; - existingUserState.dialogMessage = suspended ? dialogMessage : null; + existingUserState.dialogInfo = suspended ? dialogInfo : null; existingUserState.suspendedAppExtras = suspended ? appExtras : null; existingUserState.suspendedLauncherExtras = suspended ? launcherExtras : null; } @@ -423,7 +424,7 @@ public abstract class PackageSettingBase extends SettingBase { void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped, boolean notLaunched, boolean hidden, boolean suspended, String suspendingPackage, - String dialogMessage, PersistableBundle suspendedAppExtras, + SuspendDialogInfo dialogInfo, PersistableBundle suspendedAppExtras, PersistableBundle suspendedLauncherExtras, boolean instantApp, boolean virtualPreload, String lastDisableAppCaller, ArraySet<String> enabledComponents, ArraySet<String> disabledComponents, @@ -438,7 +439,7 @@ public abstract class PackageSettingBase extends SettingBase { state.hidden = hidden; state.suspended = suspended; state.suspendingPackage = suspendingPackage; - state.dialogMessage = dialogMessage; + state.dialogInfo = dialogInfo; state.suspendedAppExtras = suspendedAppExtras; state.suspendedLauncherExtras = suspendedLauncherExtras; state.lastDisableAppCaller = lastDisableAppCaller; diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 5c88e0637092..6a7e65400fa7 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -49,6 +49,7 @@ import android.content.pm.PackageUserState; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.Signature; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; import android.net.Uri; @@ -203,6 +204,7 @@ public final class Settings { private static final String TAG_DEFAULT_BROWSER = "default-browser"; private static final String TAG_DEFAULT_DIALER = "default-dialer"; private static final String TAG_VERSION = "version"; + private static final String TAG_SUSPENDED_DIALOG_INFO = "suspended-dialog-info"; private static final String TAG_SUSPENDED_APP_EXTRAS = "suspended-app-extras"; private static final String TAG_SUSPENDED_LAUNCHER_EXTRAS = "suspended-launcher-extras"; @@ -222,6 +224,10 @@ public final class Settings { private static final String ATTR_HIDDEN = "hidden"; private static final String ATTR_SUSPENDED = "suspended"; private static final String ATTR_SUSPENDING_PACKAGE = "suspending-package"; + /** + * @deprecated Legacy attribute, kept only for upgrading from P builds. + */ + @Deprecated private static final String ATTR_SUSPEND_DIALOG_MESSAGE = "suspend_dialog_message"; // Legacy, uninstall blocks are stored separately. @Deprecated @@ -730,7 +736,7 @@ public final class Settings { false /*hidden*/, false /*suspended*/, null /*suspendingPackage*/, - null /*dialogMessage*/, + null /*dialogInfo*/, null /*suspendedAppExtras*/, null /*suspendedLauncherExtras*/, instantApp, @@ -1620,7 +1626,7 @@ public final class Settings { false /*hidden*/, false /*suspended*/, null /*suspendingPackage*/, - null /*dialogMessage*/, + null /*dialogInfo*/, null /*suspendedAppExtras*/, null /*suspendedLauncherExtras*/, false /*instantApp*/, @@ -1730,6 +1736,7 @@ public final class Settings { ArraySet<String> disabledComponents = null; PersistableBundle suspendedAppExtras = null; PersistableBundle suspendedLauncherExtras = null; + SuspendDialogInfo suspendDialogInfo = null; int packageDepth = parser.getDepth(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT @@ -1752,20 +1759,28 @@ public final class Settings { case TAG_SUSPENDED_LAUNCHER_EXTRAS: suspendedLauncherExtras = PersistableBundle.restoreFromXml(parser); break; + case TAG_SUSPENDED_DIALOG_INFO: + suspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser); + break; default: Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag " + TAG_PACKAGE); } } + if (suspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) { + suspendDialogInfo = new SuspendDialogInfo.Builder() + .setMessage(dialogMessage) + .build(); + } if (blockUninstall) { setBlockUninstallLPw(userId, name, true); } ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched, - hidden, suspended, suspendingPackage, dialogMessage, suspendedAppExtras, - suspendedLauncherExtras, instantApp, virtualPreload, enabledCaller, - enabledComponents, disabledComponents, verifState, linkGeneration, - installReason, harmfulAppWarning); + hidden, suspended, suspendingPackage, suspendDialogInfo, + suspendedAppExtras, suspendedLauncherExtras, instantApp, virtualPreload, + enabledCaller, enabledComponents, disabledComponents, verifState, + linkGeneration, installReason, harmfulAppWarning); } else if (tagName.equals("preferred-activities")) { readPreferredActivitiesLPw(parser, userId); } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) { @@ -2076,9 +2091,10 @@ public final class Settings { serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, ustate.suspendingPackage); } - if (ustate.dialogMessage != null) { - serializer.attribute(null, ATTR_SUSPEND_DIALOG_MESSAGE, - ustate.dialogMessage); + if (ustate.dialogInfo != null) { + serializer.startTag(null, TAG_SUSPENDED_DIALOG_INFO); + ustate.dialogInfo.saveToXml(serializer); + serializer.endTag(null, TAG_SUSPENDED_DIALOG_INFO); } if (ustate.suspendedAppExtras != null) { serializer.startTag(null, TAG_SUSPENDED_APP_EXTRAS); @@ -4737,8 +4753,8 @@ public final class Settings { final PackageUserState pus = ps.readUserState(user.id); pw.print(" suspendingPackage="); pw.print(pus.suspendingPackage); - pw.print(" dialogMessage="); - pw.print(pus.dialogMessage); + pw.print(" dialogInfo="); + pw.print(pus.dialogInfo); } pw.print(" stopped="); pw.print(ps.getStopped(user.id)); diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 6ca4f2e49d0a..7d699cee0ef1 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -43,12 +43,15 @@ import android.os.Binder; import android.os.Bundle; import android.os.Environment; import android.os.FileUtils; +import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.IStatsCompanionService; import android.os.IStatsManager; import android.os.IStoraged; import android.os.IThermalEventListener; import android.os.IThermalService; +import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.Process; @@ -148,6 +151,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { public static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME"; public static final int DEATH_THRESHOLD = 10; + + static final class CompanionHandler extends Handler { + CompanionHandler(Looper looper) { + super(looper); + } + } + private final Context mContext; private final AlarmManager mAlarmManager; @GuardedBy("sStatsdLock") @@ -173,6 +183,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final HashSet<Long> mDeathTimeMillis = new HashSet<>(); @GuardedBy("sStatsdLock") private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); + private final CompanionHandler mHandler; private KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader(); private KernelCpuSpeedReader[] mKernelCpuSpeedReaders; @@ -251,6 +262,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } else { Slog.e(TAG, "cannot find thermalservice, no throttling push notifications"); } + + HandlerThread handlerThread = new HandlerThread(TAG); + handlerThread.start(); + mHandler = new CompanionHandler(handlerThread.getLooper()); + } @Override @@ -498,7 +514,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // only fire when it awakens. // AlarmManager will automatically cancel any previous mAnomalyAlarmListener alarm. mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".anomaly", - mAnomalyAlarmListener, null); + mAnomalyAlarmListener, mHandler); } finally { Binder.restoreCallingIdentity(callingToken); } @@ -529,7 +545,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will // only fire when it awakens. mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".periodic", - mPeriodicAlarmListener, null); + mPeriodicAlarmListener, mHandler); } finally { Binder.restoreCallingIdentity(callingToken); } @@ -561,7 +577,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will // only fire when it awakens. mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, TAG + ".pull", - mPullingAlarmListener, null); + mPullingAlarmListener, mHandler); } finally { Binder.restoreCallingIdentity(callingToken); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 642f57814c61..d8fd198fe143 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2077,9 +2077,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo int taskForTapOutside(int x, int y) { for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); - if (stack.isActivityTypeHome()) { + if (stack.isActivityTypeHome() && !stack.inMultiWindowMode()) { // We skip not only home stack, but also everything behind home because user can't - // see them. + // see them when home stack is isn't in multi-window mode. break; } final int taskId = stack.taskIdFromPoint(x, y); diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 5410676a49fc..b096bf2d0738 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -430,14 +430,25 @@ public abstract class WindowManagerInternal { public abstract boolean isUidFocused(int uid); /** - * Checks whether the specified process has IME focus or not. + * Checks whether the specified IME client has IME focus or not. * * @param uid UID of the process to be queried * @param pid PID of the process to be queried - * @return {@code true} if a process that is identified by {@code uid} and {@code pid} has IME - * focus + * @param displayId Display ID reported from the client. Note that this method also verifies + * whether the specified process is allowed to access to this display or not + * @return {@code true} if the IME client specified with {@code uid}, {@code pid}, and + * {@code displayId} has IME focus */ - public abstract boolean isInputMethodClientFocus(int uid, int pid); + public abstract boolean isInputMethodClientFocus(int uid, int pid, int displayId); + + /** + * Checks whether the given {@code uid} is allowed to use the given {@code displayId} or not. + * + * @param displayId Display ID to be checked + * @param uid UID to be checked. + * @return {@code true} if the given {@code uid} is allowed to use the given {@code displayId} + */ + public abstract boolean isUidAllowedOnDisplay(int displayId, int uid); /** * Return the display Id for given window. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 10ba63e0a9f7..8b1b3275362a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -45,8 +45,8 @@ import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHA import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; @@ -1928,7 +1928,7 @@ public class WindowManagerService extends IWindowManager.Stub mAccessibilityController.onSomeWindowResizedOrMovedLocked(); } - if ((flagChanges & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) { + if ((flagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) { updateNonSystemOverlayWindowsVisibilityIfNeeded( win, win.mWinAnimator.getShown()); } @@ -7201,16 +7201,20 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public boolean isInputMethodClientFocus(int uid, int pid) { + public boolean isInputMethodClientFocus(int uid, int pid, int displayId) { + if (displayId == Display.INVALID_DISPLAY) { + return false; + } synchronized (mWindowMap) { - // Check all displays if any input method window has focus. - for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) { - final DisplayContent displayContent = mRoot.mChildren.get(i); - if (displayContent.isInputMethodClientFocus(uid, pid)) { - return true; - } + final DisplayContent displayContent = mRoot.getTopFocusedDisplayContent(); + if (displayContent == null + || displayContent.getDisplayId() != displayId + || !displayContent.hasAccess(uid)) { + return false; + } + if (displayContent.isInputMethodClientFocus(uid, pid)) { + return true; } - // Okay, how about this... what is the current focus? // It seems in some cases we may not have moved the IM // target window, such as when it was in a pop-up window, @@ -7219,7 +7223,7 @@ public class WindowManagerService extends IWindowManager.Stub // press home. Sometimes the IME won't go down.) // Would be nice to fix this more correctly, but it's // way at the end of a release, and this should be good enough. - final WindowState currentFocus = mRoot.getTopFocusedDisplayContent().mCurrentFocus; + final WindowState currentFocus = displayContent.mCurrentFocus; if (currentFocus != null && currentFocus.mSession.mUid == uid && currentFocus.mSession.mPid == pid) { return true; @@ -7229,6 +7233,20 @@ public class WindowManagerService extends IWindowManager.Stub } @Override + public boolean isUidAllowedOnDisplay(int displayId, int uid) { + if (displayId == Display.DEFAULT_DISPLAY) { + return true; + } + if (displayId == Display.INVALID_DISPLAY) { + return false; + } + synchronized (mWindowMap) { + final DisplayContent displayContent = mRoot.getDisplayContent(displayId); + return displayContent != null && displayContent.hasAccess(uid); + } + } + + @Override public int getDisplayIdForWindow(IBinder windowToken) { synchronized (mWindowMap) { final WindowState window = mWindowMap.get(windowToken); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 8276952d8a6c..eacbda198aba 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -46,12 +46,12 @@ import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; @@ -3470,7 +3470,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * this window is visible. */ boolean hideNonSystemOverlayWindowsWhenVisible() { - return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0 + return (mAttrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0 && mSession.mCanHideNonSystemOverlayWindows; } diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk index 78c0be42a448..e67f8d32fb6d 100644 --- a/services/robotests/Android.mk +++ b/services/robotests/Android.mk @@ -84,7 +84,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ LOCAL_JAVA_LIBRARIES := \ junit \ - platform-robolectric-3.6.1-prebuilt + platform-robolectric-3.6.2-prebuilt LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib LOCAL_MODULE := FrameworksServicesRoboTests @@ -109,4 +109,4 @@ LOCAL_TEST_PACKAGE := FrameworksServicesLib LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java -include prebuilts/misc/common/robolectric/3.6.1/run_robotests.mk +include prebuilts/misc/common/robolectric/3.6.2/run_robotests.mk diff --git a/services/tests/mockingservicestests/Android.mk b/services/tests/mockingservicestests/Android.mk index 8c0283318419..b83a79fc232c 100644 --- a/services/tests/mockingservicestests/Android.mk +++ b/services/tests/mockingservicestests/Android.mk @@ -22,6 +22,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := \ frameworks-base-testutils \ services.core \ + services.net \ androidx-test \ mockito-target-extended-minus-junit4 \ platform-test-annotations \ diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java index 95ed00f3ad5b..8afd788256c1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java @@ -41,6 +41,9 @@ import static com.android.server.DeviceIdleController.lightStateToString; import static com.android.server.DeviceIdleController.stateToString; import static org.junit.Assert.assertEquals; + +import android.net.NetworkInfo; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -50,6 +53,8 @@ import static org.mockito.ArgumentMatchers.anyString; import android.app.ActivityManagerInternal; import android.app.AlarmManager; +import android.net.ConnectivityManager; +import android.content.Intent; import android.app.IActivityManager; import android.content.ContentResolver; import android.content.Context; @@ -83,11 +88,14 @@ public class DeviceIdleControllerTest { private DeviceIdleController mDeviceIdleController; private AnyMotionDetectorForTest mAnyMotionDetector; private AppStateTrackerForTest mAppStateTracker; + private InjectorForTest mInjector; private MockitoSession mMockingSession; @Mock private AlarmManager mAlarmManager; @Mock + private ConnectivityService mConnectivityService; + @Mock private DeviceIdleController.Constants mConstants; @Mock private IActivityManager mIActivityManager; @@ -99,6 +107,8 @@ public class DeviceIdleControllerTest { private PowerManager.WakeLock mWakeLock; class InjectorForTest extends DeviceIdleController.Injector { + ConnectivityService connectivityService; + LocationManager locationManager; InjectorForTest(Context ctx) { super(ctx); @@ -122,18 +132,19 @@ public class DeviceIdleControllerTest { @Override ConnectivityService getConnectivityService() { - return null; + return connectivityService; } @Override - DeviceIdleController.Constants getConstants(DeviceIdleController controller, Handler handler, + DeviceIdleController.Constants getConstants(DeviceIdleController controller, + Handler handler, ContentResolver resolver) { return mConstants; } @Override LocationManager getLocationManager() { - return mLocationManager; + return locationManager; } @Override @@ -201,8 +212,8 @@ public class DeviceIdleControllerTest { doNothing().when(mWakeLock).acquire(); mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper()); mAnyMotionDetector = new AnyMotionDetectorForTest(); - mDeviceIdleController = new DeviceIdleController(getContext(), - new InjectorForTest(getContext())); + mInjector = new InjectorForTest(getContext()); + mDeviceIdleController = new DeviceIdleController(getContext(), mInjector); spyOn(mDeviceIdleController); doNothing().when(mDeviceIdleController).publishBinderService(any(), any()); mDeviceIdleController.onStart(); @@ -271,6 +282,60 @@ public class DeviceIdleControllerTest { } @Test + public void testUpdateConnectivityState() { + // No connectivity service + final boolean isConnected = mDeviceIdleController.isNetworkConnected(); + mInjector.connectivityService = null; + mDeviceIdleController.updateConnectivityState(null); + assertEquals(isConnected, mDeviceIdleController.isNetworkConnected()); + + // No active network info + mInjector.connectivityService = mConnectivityService; + doReturn(null).when(mConnectivityService).getActiveNetworkInfo(); + mDeviceIdleController.updateConnectivityState(null); + assertFalse(mDeviceIdleController.isNetworkConnected()); + + // Active network info says connected. + final NetworkInfo ani = mock(NetworkInfo.class); + doReturn(ani).when(mConnectivityService).getActiveNetworkInfo(); + doReturn(true).when(ani).isConnected(); + mDeviceIdleController.updateConnectivityState(null); + assertTrue(mDeviceIdleController.isNetworkConnected()); + + // Active network info says not connected. + doReturn(false).when(ani).isConnected(); + mDeviceIdleController.updateConnectivityState(null); + assertFalse(mDeviceIdleController.isNetworkConnected()); + + // Wrong intent passed (false). + Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); + intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 3); + doReturn(true).when(ani).isConnected(); + doReturn(1).when(ani).getType(); + mDeviceIdleController.updateConnectivityState(intent); + // Wrong intent means we shouldn't update the connected state. + assertFalse(mDeviceIdleController.isNetworkConnected()); + + // Intent says connected. + doReturn(1).when(ani).getType(); + intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1); + intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + mDeviceIdleController.updateConnectivityState(intent); + assertTrue(mDeviceIdleController.isNetworkConnected()); + + // Wrong intent passed (true). + intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 3); + // Wrong intent means we shouldn't update the connected state. + assertTrue(mDeviceIdleController.isNetworkConnected()); + + // Intent says not connected. + intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1); + intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); + mDeviceIdleController.updateConnectivityState(intent); + assertFalse(mDeviceIdleController.isNetworkConnected()); + } + + @Test public void testStateActiveToStateInactive_ConditionsNotMet() { mDeviceIdleController.becomeActiveLocked("testing", 0); verifyStateConditions(STATE_ACTIVE); @@ -360,8 +425,56 @@ public class DeviceIdleControllerTest { } @Test + public void testStepIdleStateLocked_ValidStates_WithWakeFromIdleAlarmSoon() { + enterDeepState(STATE_ACTIVE); + // Return that there's an alarm coming soon. + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_ACTIVE); + + // Everything besides ACTIVE should end up as INACTIVE since the screen would be off. + + enterDeepState(STATE_INACTIVE); + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_INACTIVE); + + enterDeepState(STATE_IDLE_PENDING); + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_INACTIVE); + + enterDeepState(STATE_SENSING); + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_INACTIVE); + + enterDeepState(STATE_LOCATING); + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_INACTIVE); + + enterDeepState(STATE_IDLE); + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_INACTIVE); + + enterDeepState(STATE_IDLE_MAINTENANCE); + doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when( + mAlarmManager).getNextWakeFromIdleTime(); + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_INACTIVE); + } + + @Test public void testStepIdleStateLocked_ValidStates_NoLocationManager() { - mDeviceIdleController.setLocationManagerForTest(null); + mInjector.locationManager = null; // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon. doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime(); // Set state to INACTIVE. @@ -427,9 +540,9 @@ public class DeviceIdleControllerTest { @Test public void testStepIdleStateLocked_ValidStates_WithLocationManager_WithProviders() { + mInjector.locationManager = mLocationManager; doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString()); // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon. - // TODO: add tests for when there's a wake-from-idle alarm coming soon. doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime(); // Set state to INACTIVE. mDeviceIdleController.becomeActiveLocked("testing", 0); @@ -463,6 +576,160 @@ public class DeviceIdleControllerTest { } @Test + public void testLightStepIdleStateLocked_InvalidStates() { + mDeviceIdleController.becomeActiveLocked("testing", 0); + mDeviceIdleController.stepLightIdleStateLocked("testing"); + // stepLightIdleStateLocked doesn't handle the ACTIVE case, so the state + // should stay as ACTIVE. + verifyLightStateConditions(LIGHT_STATE_ACTIVE); + } + + /** + * Make sure stepLightIdleStateLocked doesn't change state when the state is + * LIGHT_STATE_OVERRIDE. + */ + @Test + public void testLightStepIdleStateLocked_Overriden() { + enterLightState(LIGHT_STATE_OVERRIDE); + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_OVERRIDE); + } + + @Test + public void testLightStepIdleStateLocked_ValidStates_NoActiveOps_NetworkConnected() { + setNetworkConnected(true); + mDeviceIdleController.setJobsActive(false); + mDeviceIdleController.setAlarmsActive(false); + mDeviceIdleController.setActiveIdleOpsForTest(0); + + // Set state to INACTIVE. + mDeviceIdleController.becomeActiveLocked("testing", 0); + setChargingOn(false); + setScreenOn(false); + verifyLightStateConditions(LIGHT_STATE_INACTIVE); + + // No active ops means INACTIVE should go straight to IDLE. + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + // Should just alternate between IDLE and IDLE_MAINTENANCE now. + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + } + + @Test + public void testLightStepIdleStateLocked_ValidStates_ActiveOps_NetworkConnected() { + setNetworkConnected(true); + // Set state to INACTIVE. + mDeviceIdleController.becomeActiveLocked("testing", 0); + setChargingOn(false); + setScreenOn(false); + verifyLightStateConditions(LIGHT_STATE_INACTIVE); + + // Active ops means INACTIVE should go to PRE_IDLE to wait. + mDeviceIdleController.setJobsActive(true); + mDeviceIdleController.setAlarmsActive(true); + mDeviceIdleController.setActiveIdleOpsForTest(1); + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_PRE_IDLE); + + // Even with active ops, PRE_IDLE should go to IDLE. + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + // Should just alternate between IDLE and IDLE_MAINTENANCE now. + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + } + + @Test + public void testLightStepIdleStateLocked_ValidStates_NoActiveOps_NoNetworkConnected() { + setNetworkConnected(false); + mDeviceIdleController.setJobsActive(false); + mDeviceIdleController.setAlarmsActive(false); + mDeviceIdleController.setActiveIdleOpsForTest(0); + + // Set state to INACTIVE. + mDeviceIdleController.becomeActiveLocked("testing", 0); + setChargingOn(false); + setScreenOn(false); + verifyLightStateConditions(LIGHT_STATE_INACTIVE); + + // No active ops means INACTIVE should go straight to IDLE. + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + // Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now. + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + } + + @Test + public void testLightStepIdleStateLocked_ValidStates_ActiveOps_NoNetworkConnected() { + setNetworkConnected(false); + // Set state to INACTIVE. + mDeviceIdleController.becomeActiveLocked("testing", 0); + setChargingOn(false); + setScreenOn(false); + verifyLightStateConditions(LIGHT_STATE_INACTIVE); + + // Active ops means INACTIVE should go to PRE_IDLE to wait. + mDeviceIdleController.setJobsActive(true); + mDeviceIdleController.setAlarmsActive(true); + mDeviceIdleController.setActiveIdleOpsForTest(1); + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_PRE_IDLE); + + // Even with active ops, PRE_IDLE should go to IDLE. + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + // Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now. + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK); + + mDeviceIdleController.stepLightIdleStateLocked("testing"); + verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); + } + + @Test public void testExitMaintenanceEarlyIfNeededLocked_deep_noActiveOps() { mDeviceIdleController.setJobsActive(false); mDeviceIdleController.setAlarmsActive(false); @@ -903,6 +1170,7 @@ public class DeviceIdleControllerTest { mDeviceIdleController.becomeActiveLocked("testing", 0); break; case STATE_LOCATING: + mInjector.locationManager = mLocationManager; doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider( anyString()); // Fallthrough to step loop. @@ -917,7 +1185,6 @@ public class DeviceIdleControllerTest { setScreenOn(false); setChargingOn(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); - //fail(stateToString(mDeviceIdleController.getState())); int count = 0; while (mDeviceIdleController.getState() != state) { // Stepping through each state ensures that the proper features are turned @@ -925,7 +1192,8 @@ public class DeviceIdleControllerTest { mDeviceIdleController.stepIdleStateLocked("testing"); count++; if (count > 10) { - fail(stateToString(mDeviceIdleController.getState())); + fail("Infinite loop. Check test configuration. Currently at " + + stateToString(mDeviceIdleController.getState())); } } break; @@ -954,7 +1222,8 @@ public class DeviceIdleControllerTest { count++; if (count > 10) { - fail(lightStateToString(mDeviceIdleController.getLightState())); + fail("Infinite loop. Check test configuration. Currently at " + + lightStateToString(mDeviceIdleController.getLightState())); } } break; @@ -979,6 +1248,14 @@ public class DeviceIdleControllerTest { mDeviceIdleController.updateInteractivityLocked(); } + private void setNetworkConnected(boolean connected) { + mInjector.connectivityService = mConnectivityService; + final NetworkInfo ani = mock(NetworkInfo.class); + doReturn(connected).when(ani).isConnected(); + doReturn(ani).when(mConnectivityService).getActiveNetworkInfo(); + mDeviceIdleController.updateConnectivityState(null); + } + private void verifyStateConditions(int expectedState) { int curState = mDeviceIdleController.getState(); assertEquals( diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java index 86541b95f395..65e4fa0f4aff 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java @@ -35,6 +35,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; @@ -165,17 +166,20 @@ public class ActivityStartInterceptorTest { public void testSuspendedPackage() { mAInfo.applicationInfo.flags = FLAG_SUSPENDED; final String suspendingPackage = "com.test.suspending.package"; - final String dialogMessage = "Test Message"; + final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder() + .setMessage("Test Message") + .setIcon(0x11110001) + .build(); when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID)) .thenReturn(suspendingPackage); - when(mPackageManagerInternal.getSuspendedDialogMessage(TEST_PACKAGE_NAME, TEST_USER_ID)) - .thenReturn(dialogMessage); + when(mPackageManagerInternal.getSuspendedDialogInfo(TEST_PACKAGE_NAME, TEST_USER_ID)) + .thenReturn(dialogInfo); // THEN calling intercept returns true assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); // Check intent parameters - assertEquals(dialogMessage, - mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_DIALOG_MESSAGE)); + assertEquals(dialogInfo, + mInterceptor.mIntent.getParcelableExtra(SuspendedAppActivity.EXTRA_DIALOG_INFO)); assertEquals(suspendingPackage, mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_SUSPENDING_PACKAGE)); assertEquals(TEST_PACKAGE_NAME, diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index 5c01fac8be21..062c044ac3e3 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -37,7 +37,7 @@ import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM; -import static com.android.server.am.ActivityManagerService.ANIMATE; +import static com.android.server.am.ActivityTaskManagerService.ANIMATE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -48,6 +48,7 @@ import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -206,11 +207,11 @@ public class ActivityStarterTests extends ActivityTestsBase { prepareStarter(launchFlags); final IApplicationThread caller = mock(IApplicationThread.class); - // If no caller app, return {@code null} {@link ProcessRecord}. - final ProcessRecord record = containsConditions(preconditions, PRECONDITION_NO_CALLER_APP) - ? null : new ProcessRecord(service.mAm, mock(ApplicationInfo.class), null, 0, null); - - doReturn(record).when(service.mAm).getRecordForAppLocked(anyObject()); + final WindowProcessController wpc = + containsConditions(preconditions, PRECONDITION_NO_CALLER_APP) + ? null : new WindowProcessController( + service, mock(ApplicationInfo.class),null, 0, -1, null, null, null); + doReturn(wpc).when(service).getProcessController(anyObject()); final Intent intent = new Intent(); intent.setFlags(launchFlags); @@ -354,10 +355,12 @@ public class ActivityStarterTests extends ActivityTestsBase { invocation -> { throw new RuntimeException("Not stubbed"); }); - doReturn(mockPackageManager).when(mService.mAm).getPackageManagerInternalLocked(); + doReturn(mockPackageManager).when(mService).getPackageManagerInternalLocked(); // Never review permissions doReturn(false).when(mockPackageManager).isPermissionsReviewRequired(any(), anyInt()); + doNothing().when(mockPackageManager).grantEphemeralAccess( + anyInt(), any(), anyInt(), anyInt()); final Intent intent = new Intent(); intent.addFlags(launchFlags); @@ -511,7 +514,7 @@ public class ActivityStarterTests extends ActivityTestsBase { */ @Test public void testActivityStartsLogging_noLoggingWhenDisabled() { - doReturn(false).when(mService.mAm).isActivityStartsLoggingEnabled(); + doReturn(false).when(mService).isActivityStartsLoggingEnabled(); doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger(); ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK); @@ -529,7 +532,7 @@ public class ActivityStarterTests extends ActivityTestsBase { @Test public void testActivityStartsLogging_logsWhenEnabled() { // note: conveniently this package doesn't have any activity visible - doReturn(true).when(mService.mAm).isActivityStartsLoggingEnabled(); + doReturn(true).when(mService).isActivityStartsLoggingEnabled(); doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger(); ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK) diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 2008861907a6..023f7758bd0a 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -162,7 +162,8 @@ public class ActivityTestsBase { void setupActivityManagerService( TestActivityManagerService am, TestActivityTaskManagerService atm) { - atm.setActivityManagerService(am); + atm.setActivityManagerService(am, am.mHandlerThread.getLooper(), am.mIntentFirewall, + am.mPendingIntentController); atm.mAmInternal = am.getLocalService(); am.mAtmInternal = atm.getLocalService(); // Makes sure the supervisor is using with the spy object. diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java index 79eba680c998..92211ec0b649 100644 --- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java @@ -887,7 +887,7 @@ public class TrampolineTest { } @Override - protected BackupManagerServiceInterface createBackupManagerService() { + protected BackupManagerService createBackupManagerService() { mCreateServiceCallsCount++; return sBackupManagerServiceMock; } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index c3c07880f605..517b5ade44b8 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -37,6 +37,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; +import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.os.BaseBundle; import android.os.PersistableBundle; @@ -200,13 +201,21 @@ public class PackageManagerSettingsTests { PACKAGE_NAME_1, 1L, 0.01, true, "appString1"); final PersistableBundle launcherExtras1 = getPersistableBundle( PACKAGE_NAME_1, 10L, 0.1, false, "launcherString1"); - ps1.setSuspended(true, "suspendingPackage1", "dialogMsg1", appExtras1, launcherExtras1, 0); + + final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder() + .setIcon(0x11220001) + .setTitle(0x11220002) + .setMessage("1st message") + .setNeutralButtonText(0x11220003) + .build(); + + ps1.setSuspended(true, "suspendingPackage1", dialogInfo1, appExtras1, launcherExtras1, 0); settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1); - ps2.setSuspended(true, "suspendingPackage2", "dialogMsg2", null, null, 0); + ps2.setSuspended(true, "suspendingPackage2", null, null, null, 0); settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2); - ps3.setSuspended(false, "irrelevant", "irrevelant2", null, null, 0); + ps3.setSuspended(false, "irrelevant", dialogInfo1, null, null, 0); settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3); settingsUnderTest.writePackageRestrictionsLPr(0); @@ -221,7 +230,7 @@ public class PackageManagerSettingsTests { readUserState(0); assertThat(readPus1.suspended, is(true)); assertThat(readPus1.suspendingPackage, equalTo("suspendingPackage1")); - assertThat(readPus1.dialogMessage, equalTo("dialogMsg1")); + assertThat(readPus1.dialogInfo, equalTo(dialogInfo1)); assertThat(BaseBundle.kindofEquals(readPus1.suspendedAppExtras, appExtras1), is(true)); assertThat(BaseBundle.kindofEquals(readPus1.suspendedLauncherExtras, launcherExtras1), is(true)); @@ -230,7 +239,7 @@ public class PackageManagerSettingsTests { readUserState(0); assertThat(readPus2.suspended, is(true)); assertThat(readPus2.suspendingPackage, equalTo("suspendingPackage2")); - assertThat(readPus2.dialogMessage, equalTo("dialogMsg2")); + assertThat(readPus2.dialogInfo, is(nullValue())); assertThat(readPus2.suspendedAppExtras, is(nullValue())); assertThat(readPus2.suspendedLauncherExtras, is(nullValue())); @@ -238,7 +247,7 @@ public class PackageManagerSettingsTests { readUserState(0); assertThat(readPus3.suspended, is(false)); assertThat(readPus3.suspendingPackage, is(nullValue())); - assertThat(readPus3.dialogMessage, is(nullValue())); + assertThat(readPus3.dialogInfo, is(nullValue())); assertThat(readPus3.suspendedAppExtras, is(nullValue())); assertThat(readPus3.suspendedLauncherExtras, is(nullValue())); } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java index 4a33ca37f767..f0ed612400ed 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java @@ -23,6 +23,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import android.content.pm.PackageUserState; +import android.content.pm.SuspendDialogInfo; import android.os.PersistableBundle; import android.util.ArraySet; @@ -37,7 +38,7 @@ import org.junit.runner.RunWith; public class PackageUserStateTest { @Test - public void testPackageUserState01() { + public void testPackageUserState01() { final PackageUserState testUserState = new PackageUserState(); PackageUserState oldUserState; @@ -84,7 +85,7 @@ public class PackageUserStateTest { } @Test - public void testPackageUserState02() { + public void testPackageUserState02() { final PackageUserState testUserState01 = new PackageUserState(); PackageUserState oldUserState; @@ -102,7 +103,7 @@ public class PackageUserStateTest { } @Test - public void testPackageUserState03() { + public void testPackageUserState03() { final PackageUserState oldUserState = new PackageUserState(); // only new user state has array defined; different @@ -138,7 +139,7 @@ public class PackageUserStateTest { } @Test - public void testPackageUserState04() { + public void testPackageUserState04() { final PackageUserState oldUserState = new PackageUserState(); // only new user state has array defined; different @@ -185,15 +186,19 @@ public class PackageUserStateTest { launcherExtras2.putString("name", "launcherExtras2"); final String suspendingPackage1 = "package1"; final String suspendingPackage2 = "package2"; - final String dialogMessage1 = "dialogMessage1"; - final String dialogMessage2 = "dialogMessage2"; + final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder() + .setMessage("dialogMessage1") + .build(); + final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder() + .setMessage("dialogMessage2") + .build(); final PackageUserState testUserState1 = new PackageUserState(); testUserState1.suspended = true; testUserState1.suspendedAppExtras = appExtras1; testUserState1.suspendedLauncherExtras = launcherExtras1; testUserState1.suspendingPackage = suspendingPackage1; - testUserState1.dialogMessage = dialogMessage1; + testUserState1.dialogInfo = dialogInfo1; PackageUserState testUserState2 = new PackageUserState(testUserState1); assertThat(testUserState1.equals(testUserState2), is(true)); @@ -209,14 +214,14 @@ public class PackageUserStateTest { assertThat(testUserState1.equals(testUserState2), is(false)); testUserState2 = new PackageUserState(testUserState1); - testUserState2.dialogMessage = dialogMessage2; + testUserState2.dialogInfo = dialogInfo2; assertThat(testUserState1.equals(testUserState2), is(false)); testUserState2 = new PackageUserState(testUserState1); testUserState2.suspended = testUserState1.suspended = false; // Everything is different but irrelevant if suspended is false testUserState2.suspendingPackage = suspendingPackage2; - testUserState2.dialogMessage = dialogMessage2; + testUserState2.dialogInfo = dialogInfo2; testUserState2.suspendedAppExtras = appExtras2; testUserState2.suspendedLauncherExtras = launcherExtras2; assertThat(testUserState1.equals(testUserState2), is(true)); diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java new file mode 100644 index 000000000000..7eccd6728533 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; + +import android.content.pm.SuspendDialogInfo; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class SuspendDialogInfoTest { + private static final int VALID_TEST_RES_ID_1 = 0x11110001; + private static final int VALID_TEST_RES_ID_2 = 0x11110002; + + private static SuspendDialogInfo.Builder createDefaultDialogBuilder() { + return new SuspendDialogInfo.Builder() + .setIcon(VALID_TEST_RES_ID_1) + .setTitle(VALID_TEST_RES_ID_1) + .setMessage(VALID_TEST_RES_ID_1) + .setNeutralButtonText(VALID_TEST_RES_ID_1); + } + + @Test + public void equalsComparesIcons() { + final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder(); + final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder(); + assertEquals(dialogBuilder1.build(), dialogBuilder2.build()); + // Only icon is different + dialogBuilder2.setIcon(VALID_TEST_RES_ID_2); + assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build()); + } + + @Test + public void equalsComparesTitle() { + final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder(); + final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder(); + assertEquals(dialogBuilder1.build(), dialogBuilder2.build()); + // Only title is different + dialogBuilder2.setTitle(VALID_TEST_RES_ID_2); + assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build()); + } + + @Test + public void equalsComparesButtonText() { + final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder(); + final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder(); + assertEquals(dialogBuilder1.build(), dialogBuilder2.build()); + // Only button text is different + dialogBuilder2.setNeutralButtonText(VALID_TEST_RES_ID_2); + assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build()); + } + + @Test + public void equalsComparesMessageIds() { + final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder(); + final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder(); + assertEquals(dialogBuilder1.build(), dialogBuilder2.build()); + // Only message is different + dialogBuilder2.setMessage(VALID_TEST_RES_ID_2); + assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build()); + } + + @Test + public void equalsIgnoresMessageStringsWhenIdsSet() { + final SuspendDialogInfo.Builder dialogBuilder1 = new SuspendDialogInfo.Builder() + .setMessage(VALID_TEST_RES_ID_1) + .setMessage("1st message"); + final SuspendDialogInfo.Builder dialogBuilder2 = new SuspendDialogInfo.Builder() + .setMessage(VALID_TEST_RES_ID_1) + .setMessage("2nd message"); + // String messages different but should get be ignored when resource ids are set + assertEquals(dialogBuilder1.build(), dialogBuilder2.build()); + } + + @Test + public void equalsComparesMessageStringsWhenNoIdsSet() { + final SuspendDialogInfo.Builder dialogBuilder1 = new SuspendDialogInfo.Builder() + .setMessage("1st message"); + final SuspendDialogInfo.Builder dialogBuilder2 = new SuspendDialogInfo.Builder() + .setMessage("2nd message"); + // Both have different messages, which are not ignored as resource ids aren't set + assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build()); + } + + @Test + public void messageStringClearedWhenResIdSet() { + final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder() + .setMessage(VALID_TEST_RES_ID_2) + .setMessage("Should be cleared on build") + .build(); + assertNull(dialogInfo.getDialogMessage()); + assertEquals(VALID_TEST_RES_ID_2, dialogInfo.getDialogMessageResId()); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java index f115b9cd0fc5..553d234adfca 100644 --- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java @@ -33,6 +33,7 @@ import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; +import android.content.pm.SuspendDialogInfo; import android.content.res.Resources; import android.os.BaseBundle; import android.os.Bundle; @@ -152,7 +153,7 @@ public class SuspendPackagesTest { } void drainPendingBroadcasts() { - while (pollForIntent(5) != null); + while (pollForIntent(5) != null) ; } Intent receiveIntentFromApp() { @@ -215,15 +216,15 @@ public class SuspendPackagesTest { } private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras, - String dialogMessage) { + SuspendDialogInfo dialogInfo) { final String[] unchangedPackages = mPackageManager.setPackagesSuspended( - PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogMessage); + PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogInfo); assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0); } private void unsuspendTestPackage() { final String[] unchangedPackages = mPackageManager.setPackagesSuspended( - PACKAGES_TO_SUSPEND, false, null, null, null); + PACKAGES_TO_SUSPEND, false, null, null, (SuspendDialogInfo) null); assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0); } @@ -318,7 +319,8 @@ public class SuspendPackagesTest { @Test public void testCannotSuspendSelf() { final String[] unchangedPkgs = mPackageManager.setPackagesSuspended( - new String[]{mContext.getOpPackageName()}, true, null, null, null); + new String[]{mContext.getOpPackageName()}, true, null, null, + (SuspendDialogInfo) null); assertTrue(unchangedPkgs.length == 1); assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]); } @@ -457,7 +459,8 @@ public class SuspendPackagesTest { mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, ACTION_REPORT_TEST_ACTIVITY_STARTED); final String testMessage = "This is a test message to report suspension of %1$s"; - suspendTestPackage(null, null, testMessage); + suspendTestPackage(null, null, + new SuspendDialogInfo.Builder().setMessage(testMessage).build()); startTestAppActivity(); assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2)); assertNotNull("Given dialog message not shown", mUiDevice.wait( diff --git a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java index 60025f0f03fe..ae40f7e7d235 100644 --- a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java @@ -334,7 +334,7 @@ public class ScreenDecorWindowTests { final Activity activity = mInstrumentation.startActivitySync(intent, options.toBundle()); waitForIdle(); - assertEquals(displayId, activity.getDisplay().getDisplayId()); + assertEquals(displayId, activity.getDisplayId()); return activity; } diff --git a/startop/tools/view_compiler/Android.bp b/startop/tools/view_compiler/Android.bp index c3e91849e636..3681529643bc 100644 --- a/startop/tools/view_compiler/Android.bp +++ b/startop/tools/view_compiler/Android.bp @@ -14,19 +14,30 @@ // limitations under the License. // +cc_defaults { + name: "viewcompiler_defaults", + shared_libs: [ + "libdexfile", + "slicer", + ], +} + cc_library_host_static { name: "libviewcompiler", + defaults: ["viewcompiler_defaults"], srcs: [ + "dex_builder.cc", "java_lang_builder.cc", "util.cc", ], static_libs: [ - "libbase" - ] + "libbase", + ], } cc_binary_host { name: "viewcompiler", + defaults: ["viewcompiler_defaults"], srcs: [ "main.cc", ], @@ -40,10 +51,12 @@ cc_binary_host { cc_test_host { name: "view-compiler-tests", + defaults: ["viewcompiler_defaults"], srcs: [ + "dex_builder_test.cc", "util_test.cc", ], static_libs: [ "libviewcompiler", - ] + ], } diff --git a/startop/tools/view_compiler/dex_builder.cc b/startop/tools/view_compiler/dex_builder.cc new file mode 100644 index 000000000000..7a9f41fd8f38 --- /dev/null +++ b/startop/tools/view_compiler/dex_builder.cc @@ -0,0 +1,214 @@ +/* + * 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 "dex_builder.h" + +#include "dex/descriptors_names.h" +#include "dex/dex_instruction.h" + +#include <fstream> +#include <memory> + +namespace startop { +namespace dex { + +using std::shared_ptr; +using std::string; + +using art::Instruction; +using ::dex::kAccPublic; + +const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; }; +const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; }; + +namespace { +// From https://source.android.com/devices/tech/dalvik/dex-format#dex-file-magic +constexpr uint8_t kDexFileMagic[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x38, 0x00}; + +// Strings lengths can be 32 bits long, but encoded as LEB128 this can take up to five bytes. +constexpr size_t kMaxEncodedStringLength{5}; + +} // namespace + +void* TrackingAllocator::Allocate(size_t size) { + std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size); + void* raw_buffer = buffer.get(); + allocations_[raw_buffer] = std::move(buffer); + return raw_buffer; +} + +void TrackingAllocator::Free(void* ptr) { allocations_.erase(allocations_.find(ptr)); } + +// Write out a DEX file that is basically: +// +// package dextest; +// public class DexTest { +// public static int foo() { return 5; } +// } +void WriteTestDexFile(const string& filename) { + DexBuilder dex_file; + + ClassBuilder cbuilder{dex_file.MakeClass("dextest.DexTest")}; + cbuilder.set_source_file("dextest.java"); + + MethodBuilder method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int()})}; + + MethodBuilder::Register r = method.MakeRegister(); + method.BuildConst4(r, 5); + method.BuildReturn(r); + + method.Encode(); + + slicer::MemView image{dex_file.CreateImage()}; + + std::ofstream out_file(filename); + out_file.write(image.ptr<const char>(), image.size()); +} + +DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} { + dex_file_->magic = slicer::MemView{kDexFileMagic, sizeof(kDexFileMagic)}; +} + +slicer::MemView DexBuilder::CreateImage() { + ::dex::Writer writer(dex_file_); + size_t image_size{0}; + ::dex::u1* image = writer.CreateImage(&allocator_, &image_size); + return slicer::MemView{image, image_size}; +} + +ir::String* DexBuilder::GetOrAddString(const std::string& string) { + ir::String*& entry = strings_[string]; + + if (entry == nullptr) { + // Need to encode the length and then write out the bytes, including 1 byte for null terminator + auto buffer = std::make_unique<uint8_t[]>(string.size() + kMaxEncodedStringLength + 1); + uint8_t* string_data_start = ::dex::WriteULeb128(buffer.get(), string.size()); + + size_t header_length = + reinterpret_cast<uintptr_t>(string_data_start) - reinterpret_cast<uintptr_t>(buffer.get()); + + auto end = std::copy(string.begin(), string.end(), string_data_start); + *end = '\0'; + + entry = Alloc<ir::String>(); + // +1 for null terminator + entry->data = slicer::MemView{buffer.get(), header_length + string.size() + 1}; + string_data_.push_back(std::move(buffer)); + } + return entry; +} + +ClassBuilder DexBuilder::MakeClass(const std::string& name) { + auto* class_def = Alloc<ir::Class>(); + ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str())); + type_def->class_def = class_def; + + class_def->type = type_def; + class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object")); + class_def->access_flags = kAccPublic; + return ClassBuilder{this, class_def}; +} + +// TODO(eholk): we probably want GetOrAddString() also +ir::Type* DexBuilder::GetOrAddType(const std::string& descriptor) { + if (types_by_descriptor_.find(descriptor) != types_by_descriptor_.end()) { + return types_by_descriptor_[descriptor]; + } + + ir::Type* type = Alloc<ir::Type>(); + type->descriptor = GetOrAddString(descriptor); + types_by_descriptor_[descriptor] = type; + return type; +} + +ir::Proto* Prototype::Encode(DexBuilder* dex) const { + auto* proto = dex->Alloc<ir::Proto>(); + proto->shorty = dex->GetOrAddString(Shorty()); + proto->return_type = dex->GetOrAddType(return_type_.descriptor()); + if (param_types_.size() > 0) { + proto->param_types = dex->Alloc<ir::TypeList>(); + for (const auto& param_type : param_types_) { + proto->param_types->types.push_back(dex->GetOrAddType(param_type.descriptor())); + } + } else { + proto->param_types = nullptr; + } + return proto; +} + +std::string Prototype::Shorty() const { + std::string shorty; + shorty.append(return_type_.short_descriptor()); + for (const auto& type_descriptor : param_types_) { + shorty.append(type_descriptor.short_descriptor()); + } + return shorty; +} + +ClassBuilder::ClassBuilder(DexBuilder* parent, ir::Class* class_def) + : parent_(parent), class_(class_def) {} + +MethodBuilder ClassBuilder::CreateMethod(const std::string& name, Prototype prototype) { + ir::String* dex_name{parent_->GetOrAddString(name)}; + + auto* decl = parent_->Alloc<ir::MethodDecl>(); + decl->name = dex_name; + decl->parent = class_->type; + decl->prototype = prototype.Encode(parent_); + + return MethodBuilder{parent_, class_, decl}; +} + +void ClassBuilder::set_source_file(const string& source) { + class_->source_file = parent_->GetOrAddString(source); +} + +MethodBuilder::MethodBuilder(DexBuilder* dex, ir::Class* class_def, ir::MethodDecl* decl) + : dex_{dex}, class_{class_def}, decl_{decl} {} + +ir::EncodedMethod* MethodBuilder::Encode() { + auto* method = dex_->Alloc<ir::EncodedMethod>(); + method->decl = decl_; + + // TODO: make access flags configurable + method->access_flags = kAccPublic | ::dex::kAccStatic; + + auto* code = dex_->Alloc<ir::Code>(); + code->registers = num_registers_; + // TODO: support ins and outs + code->instructions = slicer::ArrayView<const ::dex::u2>(buffer_.data(), buffer_.size()); + method->code = code; + + class_->direct_methods.push_back(method); + + return method; +} + +MethodBuilder::Register MethodBuilder::MakeRegister() { return num_registers_++; } + +void MethodBuilder::BuildReturn() { buffer_.push_back(Instruction::RETURN_VOID); } + +void MethodBuilder::BuildReturn(Register src) { buffer_.push_back(Instruction::RETURN | src << 8); } + +void MethodBuilder::BuildConst4(Register target, int value) { + DCHECK_LT(value, 16); + // TODO: support more registers + DCHECK_LT(target, 16); + buffer_.push_back(Instruction::CONST_4 | (value << 12) | (target << 8)); +} + +} // namespace dex +} // namespace startop diff --git a/startop/tools/view_compiler/dex_builder.h b/startop/tools/view_compiler/dex_builder.h new file mode 100644 index 000000000000..d280abce21f5 --- /dev/null +++ b/startop/tools/view_compiler/dex_builder.h @@ -0,0 +1,189 @@ +/* + * 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 DEX_BUILDER_H_ +#define DEX_BUILDER_H_ + +#include <map> +#include <string> +#include <vector> + +#include "slicer/dex_ir.h" +#include "slicer/writer.h" + +namespace startop { +namespace dex { + +// TODO: remove this once the dex generation code is complete. +void WriteTestDexFile(const std::string& filename); + +////////////////////////// +// Forward declarations // +////////////////////////// +class DexBuilder; + +// Our custom allocator for dex::Writer +// +// This keeps track of all allocations and ensures they are freed when +// TrackingAllocator is destroyed. Pointers to memory allocated by this +// allocator must not outlive the allocator. +class TrackingAllocator : public ::dex::Writer::Allocator { + public: + virtual void* Allocate(size_t size); + virtual void Free(void* ptr); + + private: + std::map<void*, std::unique_ptr<uint8_t[]>> allocations_; +}; + +// Represents a DEX type descriptor. +// +// TODO: add a way to create a descriptor for a reference of a class type. +class TypeDescriptor { + public: + // Named constructors for base type descriptors. + static const TypeDescriptor Int(); + static const TypeDescriptor Void(); + + // Return the full descriptor, such as I or Ljava/lang/Object + const std::string& descriptor() const { return descriptor_; } + // Return the shorty descriptor, such as I or L + std::string short_descriptor() const { return descriptor().substr(0, 1); } + + private: + TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {} + + const std::string descriptor_; +}; + +// Defines a function signature. For example, Prototype{TypeDescriptor::VOID, TypeDescriptor::Int} +// represents the function type (Int) -> Void. +class Prototype { + public: + template <typename... TypeDescriptors> + Prototype(TypeDescriptor return_type, TypeDescriptors... param_types) + : return_type_{return_type}, param_types_{param_types...} {} + + // Encode this prototype into the dex file. + ir::Proto* Encode(DexBuilder* dex) const; + + // Get the shorty descriptor, such as VII for (Int, Int) -> Void + std::string Shorty() const; + + private: + const TypeDescriptor return_type_; + const std::vector<TypeDescriptor> param_types_; +}; + +// Tools to help build methods and their bodies. +class MethodBuilder { + public: + MethodBuilder(DexBuilder* dex, ir::Class* class_def, ir::MethodDecl* decl); + + // Encode the method into DEX format. + ir::EncodedMethod* Encode(); + + // Registers are just represented by their number. + using Register = size_t; + + // Create a new register to be used to storing values. Note that these are not SSA registers, like + // might be expected in similar code generators. This does no liveness tracking or anything, so + // it's up to the caller to reuse registers as appropriate. + Register MakeRegister(); + + ///////////////////////////////// + // Instruction builder methods // + ///////////////////////////////// + + // return-void + void BuildReturn(); + void BuildReturn(Register src); + // const/4 + void BuildConst4(Register target, int value); + + // TODO: add builders for more instructions + + private: + DexBuilder* dex_; + ir::Class* class_; + ir::MethodDecl* decl_; + + // A buffer to hold instructions we are generating. + std::vector<::dex::u2> buffer_; + + // How many registers we've allocated + size_t num_registers_; +}; + +// A helper to build class definitions. +class ClassBuilder { + public: + ClassBuilder(DexBuilder* parent, ir::Class* class_def); + + void set_source_file(const std::string& source); + + // Create a method with the given name and prototype. The returned MethodBuilder can be used to + // fill in the method body. + MethodBuilder CreateMethod(const std::string& name, Prototype prototype); + + private: + DexBuilder* parent_; + ir::Class* class_; +}; + +// Builds Dex files from scratch. +class DexBuilder { + public: + DexBuilder(); + + // Create an in-memory image of the DEX file that can either be loaded directly or written to a + // file. + slicer::MemView CreateImage(); + + template <typename T> + T* Alloc() { + return dex_file_->Alloc<T>(); + } + + // Find the ir::String that matches the given string, creating it if it does not exist. + ir::String* GetOrAddString(const std::string& string); + // Create a new class of the given name. + ClassBuilder MakeClass(const std::string& name); + + // Add a type for the given descriptor, or return the existing one if it already exists. + // See the TypeDescriptor class for help generating these. + ir::Type* GetOrAddType(const std::string& descriptor); + + private: + std::shared_ptr<ir::DexFile> dex_file_; + + // allocator_ is needed to be able to encode the image. + TrackingAllocator allocator_; + + // We'll need to allocate buffers for all of the encoded strings we create. This is where we store + // all of them. + std::vector<std::unique_ptr<uint8_t[]>> string_data_; + + // Keep track of what types we've defined so we can look them up later. + std::map<std::string, ir::Type*> types_by_descriptor_; + + // Keep track of what strings we've defined so we can look them up later. + std::map<std::string, ir::String*> strings_; +}; + +} // namespace dex +} // namespace startop + +#endif // DEX_BUILDER_H_ diff --git a/startop/tools/view_compiler/dex_builder_test.cc b/startop/tools/view_compiler/dex_builder_test.cc new file mode 100644 index 000000000000..0d8b8541caeb --- /dev/null +++ b/startop/tools/view_compiler/dex_builder_test.cc @@ -0,0 +1,82 @@ +/* + * 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 "dex_builder.h" + +#include "dex/art_dex_file_loader.h" +#include "dex/dex_file.h" +#include "gtest/gtest.h" + +using namespace startop::dex; + +// Takes a DexBuilder, encodes it into an in-memory DEX file, verifies the resulting DEX file and +// returns whether the verification was successful. +bool EncodeAndVerify(DexBuilder* dex_file) { + slicer::MemView image{dex_file->CreateImage()}; + + art::ArtDexFileLoader loader; + std::string error_msg; + std::unique_ptr<const art::DexFile> loaded_dex_file{loader.Open(image.ptr<const uint8_t>(), + image.size(), + /*location=*/"", + /*location_checksum=*/0, + /*oat_dex_file=*/nullptr, + /*verify=*/true, + /*verify_checksum=*/false, + &error_msg)}; + return loaded_dex_file != nullptr; +} + +TEST(DexBuilderTest, VerifyDexWithClassMethod) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + auto method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Void()})}; + method.BuildReturn(); + method.Encode(); + + EXPECT_TRUE(EncodeAndVerify(&dex_file)); +} + +// Makes sure a bad DEX class fails to verify. +TEST(DexBuilderTest, VerifyBadDexWithClassMethod) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + // This method has the error, because methods cannot take Void() as a parameter. + auto method{ + cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Void(), TypeDescriptor::Void()})}; + method.BuildReturn(); + method.Encode(); + + EXPECT_FALSE(EncodeAndVerify(&dex_file)); +} + +TEST(DexBuilderTest, VerifyDexReturn5) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + auto method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int()})}; + auto r = method.MakeRegister(); + method.BuildConst4(r, 5); + method.BuildReturn(r); + method.Encode(); + + EXPECT_TRUE(EncodeAndVerify(&dex_file)); +} diff --git a/startop/tools/view_compiler/main.cc b/startop/tools/view_compiler/main.cc index 0ad7e24feb3b..7d791c229a98 100644 --- a/startop/tools/view_compiler/main.cc +++ b/startop/tools/view_compiler/main.cc @@ -16,6 +16,7 @@ #include "gflags/gflags.h" +#include "dex_builder.h" #include "java_lang_builder.h" #include "util.h" @@ -27,15 +28,17 @@ #include <string> #include <vector> +namespace { + using namespace tinyxml2; using std::string; constexpr char kStdoutFilename[]{"stdout"}; -DEFINE_string(package, "", "The package name for the generated class (required)"); +DEFINE_bool(dex, false, "Generate a DEX file instead of Java"); DEFINE_string(out, kStdoutFilename, "Where to write the generated class"); +DEFINE_string(package, "", "The package name for the generated class (required)"); -namespace { class ViewCompilerXmlVisitor : public XMLVisitor { public: ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {} @@ -63,6 +66,7 @@ class ViewCompilerXmlVisitor : public XMLVisitor { private: JavaLangViewBuilder* builder_; }; + } // end namespace int main(int argc, char** argv) { @@ -82,6 +86,11 @@ int main(int argc, char** argv) { return 1; } + if (FLAGS_dex) { + startop::dex::WriteTestDexFile("test.dex"); + return 0; + } + const char* const filename = argv[kFileNameParam]; const string layout_name = FindLayoutNameFromFilename(filename); @@ -102,4 +111,4 @@ int main(int argc, char** argv) { xml.Accept(&visitor); return 0; -}
\ No newline at end of file +} diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index d33a537f2194..3127b3584dd9 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -676,7 +676,7 @@ public class TelecomManager { /** * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static TelecomManager from(Context context) { return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index e0ec2c50ab5b..bfbcd5751bf4 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -21,6 +21,7 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -246,7 +247,7 @@ public class ServiceState implements Parcelable { private String mDataOperatorAlphaLong; private String mDataOperatorAlphaShort; private String mDataOperatorNumeric; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private boolean mIsManualNetworkSelection; private boolean mIsEmergencyOnly; @@ -256,9 +257,9 @@ public class ServiceState implements Parcelable { @UnsupportedAppUsage private boolean mCssIndicator; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private int mNetworkId; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private int mSystemId; @UnsupportedAppUsage private int mCdmaRoamingIndicator; @@ -456,7 +457,7 @@ public class ServiceState implements Parcelable { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public int getVoiceRegState() { return mVoiceRegState; } @@ -471,7 +472,7 @@ public class ServiceState implements Parcelable { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public int getDataRegState() { return mDataRegState; } @@ -532,7 +533,7 @@ public class ServiceState implements Parcelable { * @return roaming status * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public boolean getVoiceRoaming() { return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING; } @@ -556,7 +557,7 @@ public class ServiceState implements Parcelable { * @return roaming type * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public boolean getDataRoaming() { return getDataRoamingType() != ROAMING_TYPE_NOT_ROAMING; } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index f85069385f3c..40ba2b6c2355 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -1369,7 +1369,7 @@ public class SubscriptionManager { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static int getPhoneId(int subId) { if (!isValidSubscriptionId(subId)) { if (DBG) { @@ -1665,7 +1665,7 @@ public class SubscriptionManager { * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static boolean isUsableSubIdValue(int subId) { return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE; } @@ -1683,7 +1683,7 @@ public class SubscriptionManager { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) { int[] subIds = SubscriptionManager.getSubId(phoneId); if (subIds != null && subIds.length > 0) { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fca14c823751..914ff1f85c19 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -230,7 +230,8 @@ public class TelephonyManager { /** @hide /* @deprecated - use getSystemService as described above */ - @UnsupportedAppUsage + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static TelephonyManager getDefault() { return sInstance; } @@ -319,7 +320,7 @@ public class TelephonyManager { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static TelephonyManager from(Context context) { return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); } @@ -1618,8 +1619,7 @@ public class TelephonyManager { ITelephony telephony = getITelephony(); if (telephony == null) return null; - return telephony.getNeighboringCellInfo(mContext.getOpPackageName(), - mContext.getApplicationInfo().targetSdkVersion); + return telephony.getNeighboringCellInfo(mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -1906,7 +1906,7 @@ public class TelephonyManager { * @param subId * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getNetworkOperatorName(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, ""); @@ -1934,7 +1934,7 @@ public class TelephonyManager { * @param subId * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getNetworkOperator(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getNetworkOperatorForPhone(phoneId); @@ -2258,7 +2258,7 @@ public class TelephonyManager { * @hide */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public int getDataNetworkType(int subId) { try{ ITelephony telephony = getITelephony(); @@ -2294,7 +2294,7 @@ public class TelephonyManager { * @hide */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public int getVoiceNetworkType(int subId) { try{ ITelephony telephony = getITelephony(); @@ -2777,7 +2777,7 @@ public class TelephonyManager { * @param subId for which SimOperator is returned * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSimOperator(int subId) { return getSimOperatorNumeric(subId); } @@ -2791,7 +2791,7 @@ public class TelephonyManager { * @see #getSimState * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSimOperatorNumeric() { int subId = mSubId; if (!SubscriptionManager.isUsableSubIdValue(subId)) { @@ -2820,7 +2820,7 @@ public class TelephonyManager { * @param subId for which SimOperator is returned * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSimOperatorNumeric(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getSimOperatorNumericForPhone(phoneId); @@ -2834,7 +2834,7 @@ public class TelephonyManager { * @param phoneId for which SimOperator is returned * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSimOperatorNumericForPhone(int phoneId) { return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, ""); @@ -2861,7 +2861,7 @@ public class TelephonyManager { * @param subId for which SimOperatorName is returned * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSimOperatorName(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getSimOperatorNameForPhone(phoneId); @@ -2891,7 +2891,7 @@ public class TelephonyManager { * @param subId for which SimCountryIso is returned * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSimCountryIso(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getSimCountryIsoForPhone(phoneId); @@ -3103,7 +3103,7 @@ public class TelephonyManager { * @hide */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSubscriberId(int subId) { try { IPhoneSubInfo info = getSubscriberInfo(); @@ -3488,7 +3488,7 @@ public class TelephonyManager { * @hide */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getMsisdn(int subId) { try { IPhoneSubInfo info = getSubscriberInfo(); @@ -4421,7 +4421,7 @@ public class TelephonyManager { /** * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private ITelephony getITelephony() { return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); } @@ -7945,7 +7945,7 @@ public class TelephonyManager { * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public ServiceState getServiceStateForSubscriber(int subId) { try { ITelephony service = getITelephony(); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 32eb12b49cf0..1087fce21316 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -280,7 +280,7 @@ interface ITelephony { /** * Returns the neighboring cell information of the device. */ - List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg, int targetSdk); + List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg); int getCallState(); diff --git a/test-mock/api/system-current.txt b/test-mock/api/system-current.txt index 3bd3d68ba6cf..2b968aec1496 100644 --- a/test-mock/api/system-current.txt +++ b/test-mock/api/system-current.txt @@ -29,6 +29,7 @@ package android.test.mock { method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener); method public void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle); method public boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int); + method public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String); method public void setUpdateAvailable(java.lang.String, boolean); method public boolean updateIntentVerificationStatusAsUser(java.lang.String, int, int); method public void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle); diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index 9d260ebf7231..fa5b896ea126 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -774,6 +774,12 @@ public class MockContext extends Context { /** @hide */ @Override + public int getDisplayId() { + throw new UnsupportedOperationException(); + } + + /** @hide */ + @Override public void updateDisplay(int displayId) { throw new UnsupportedOperationException(); } diff --git a/tools/hiddenapi/sort_api.sh b/tools/hiddenapi/sort_api.sh index 76a2f2d6eba1..710da40585ac 100755 --- a/tools/hiddenapi/sort_api.sh +++ b/tools/hiddenapi/sort_api.sh @@ -21,4 +21,6 @@ A=( $(uniq <<< "${A[*]}") ) A=( ${C[*]} ${A[*]} ) unset IFS # Dump array back into the file -printf '%s\n' "${A[@]}" > "$dest_list" +if [ ${#A[@]} -ne 0 ]; then + printf '%s\n' "${A[@]}" > "$dest_list" +fi diff --git a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java b/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java deleted file mode 100644 index f5cad139bd23..000000000000 --- a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A class representing wifi wake reason accounting. - */ - -/** @hide */ -public class WifiWakeReasonAndCounts implements Parcelable { - private static final String TAG = "WifiWakeReasonAndCounts"; - /** - * Wlan can wake host, only when it is cmd/event, local driver-fw - * functions(non-data, non cmd/event) and rx data.The first packet - * from wlan that woke up a sleep host is what is accounted here. - * Total wlan wake to application processor would be: - * [cmdEventWake + driverFwLocalWake + totalRxDataWake] - * A further classification is provided for identifying the reasons - * for wakeup. - */ - public int totalCmdEventWake; - public int totalDriverFwLocalWake; - public int totalRxDataWake; - - public int rxUnicast; - public int rxMulticast; - public int rxBroadcast; - - public int icmp; - public int icmp6; - public int icmp6Ra; - public int icmp6Na; - public int icmp6Ns; - - public int ipv4RxMulticast; - public int ipv6Multicast; - public int otherRxMulticast; - public int[] cmdEventWakeCntArray; - public int[] driverFWLocalWakeCntArray; - - /* {@hide} */ - public WifiWakeReasonAndCounts () { - } - - @Override - /* {@hide} */ - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(" totalCmdEventWake ").append(totalCmdEventWake); - sb.append(" totalDriverFwLocalWake ").append(totalDriverFwLocalWake); - sb.append(" totalRxDataWake ").append(totalRxDataWake); - - sb.append(" rxUnicast ").append(rxUnicast); - sb.append(" rxMulticast ").append(rxMulticast); - sb.append(" rxBroadcast ").append(rxBroadcast); - - sb.append(" icmp ").append(icmp); - sb.append(" icmp6 ").append(icmp6); - sb.append(" icmp6Ra ").append(icmp6Ra); - sb.append(" icmp6Na ").append(icmp6Na); - sb.append(" icmp6Ns ").append(icmp6Ns); - - sb.append(" ipv4RxMulticast ").append(ipv4RxMulticast); - sb.append(" ipv6Multicast ").append(ipv6Multicast); - sb.append(" otherRxMulticast ").append(otherRxMulticast); - for (int i = 0; i < cmdEventWakeCntArray.length; i++) { - sb.append(" cmdEventWakeCntArray[" + i + "] " + cmdEventWakeCntArray[i]); - } - for (int i = 0; i < driverFWLocalWakeCntArray.length; i++) { - sb.append(" driverFWLocalWakeCntArray[" + i + "] " + driverFWLocalWakeCntArray[i]); - } - - return sb.toString(); - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public int describeContents() { - return 0; - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(totalCmdEventWake); - dest.writeInt(totalDriverFwLocalWake); - dest.writeInt(totalRxDataWake); - - dest.writeInt(rxUnicast); - dest.writeInt(rxMulticast); - dest.writeInt(rxBroadcast); - - dest.writeInt(icmp); - dest.writeInt(icmp6); - dest.writeInt(icmp6Ra); - dest.writeInt(icmp6Na); - dest.writeInt(icmp6Ns); - - dest.writeInt(ipv4RxMulticast); - dest.writeInt(ipv6Multicast); - dest.writeInt(otherRxMulticast); - dest.writeIntArray(cmdEventWakeCntArray); - dest.writeIntArray(driverFWLocalWakeCntArray); - } - - /* Implement the Parcelable interface - * {@hide} - */ - public static final Creator<WifiWakeReasonAndCounts> CREATOR = - new Creator<WifiWakeReasonAndCounts>() { - public WifiWakeReasonAndCounts createFromParcel(Parcel in) { - WifiWakeReasonAndCounts counts = new WifiWakeReasonAndCounts(); - counts.totalCmdEventWake = in.readInt(); - counts.totalDriverFwLocalWake = in.readInt(); - counts.totalRxDataWake = in.readInt(); - - counts.rxUnicast = in.readInt(); - counts.rxMulticast = in.readInt(); - counts.rxBroadcast = in.readInt(); - - counts.icmp = in.readInt(); - counts.icmp6 = in.readInt(); - counts.icmp6Ra = in.readInt(); - counts.icmp6Na = in.readInt(); - counts.icmp6Ns = in.readInt(); - - counts.ipv4RxMulticast = in.readInt(); - counts.ipv6Multicast = in.readInt(); - counts.otherRxMulticast = in.readInt(); - in.readIntArray(counts.cmdEventWakeCntArray); - in.readIntArray(counts.driverFWLocalWakeCntArray); - return counts; - } - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public WifiWakeReasonAndCounts[] newArray(int size) { - return new WifiWakeReasonAndCounts[size]; - } - }; -} |