Merge "Run alarms on a custom thread."
diff --git a/Android.mk b/Android.mk
index d333074..ba153ee 100644
--- a/Android.mk
+++ b/Android.mk
@@ -87,6 +87,7 @@
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 @@
--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 9269d97..0ffa38b 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -15407,6 +15407,69 @@
}
+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 @@
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 @@
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 @@
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 83a789a..eccc0ea 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -222,7 +222,7 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
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.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 @@
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 957a9b4..4604510 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -638,7 +638,7 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
}
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 @@
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 @@
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 @@
optional int32 version = 3;
- optional int64 time = 4;
+ optional int64 time_micros = 4;
}
/**
@@ -2246,11 +2246,11 @@
// 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 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 @@
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 @@
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 @@
* 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 @@
* 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 BatteryVoltage {
// The voltage of the battery, in millivolts.
- optional int32 voltage_mV = 1;
+ optional int32 voltage_millivolt = 1;
}
/**
@@ -2445,7 +2445,7 @@
optional string sensor_name = 2;
// Temperature in tenths of a degree C.
- optional int32 temperature_dC = 3;
+ optional int32 temperature_deci_celsius = 3;
}
/**
@@ -2555,8 +2555,7 @@
// recorded_message_count.
//
// If recorded_message_count is different than message_count, it means data
- // collection has been sampled. All the fields below will be sampled in this
- // case.
+ // collection has been sampled. The fields below will be sampled in this case.
optional int64 recorded_message_count = 7;
// Total latency of all processed messages.
@@ -2572,6 +2571,32 @@
// True if the screen was interactive PowerManager#isInteractive at the end of the call.
optional bool screen_interactive = 10;
+
+ // Max recorded CPU usage of all processed messages.
+ optional int64 recorded_max_cpu_micros = 11;
+
+ // Max recorded latency of all processed messages.
+ optional int64 recorded_max_latency_micros = 12;
+
+ // Total number of messages we tracked the dispatching delay for. If we
+ // collected data for all the messages, message_count will be equal to
+ // recorded_delay_message_count.
+ //
+ // If recorded_delay_message_count is different than message_count, it means data
+ // collection has been sampled or/and not all messages specified the target dispatch time.
+ // The fields below will be sampled in this case.
+ optional int64 recorded_delay_message_count = 13;
+
+ // Total dispatching delay of all processed messages.
+ // Calculated as a difference between the target dispatching time (Message.when)
+ // and the actual dispatching time.
+ // Average can be computed using recorded_total_delay_millis / recorded_delay_message_count.
+ optional int64 recorded_total_delay_millis = 14;
+
+ // Max dispatching delay of all processed messages.
+ // Calculated as a difference between the target dispatching time (Message.when)
+ // and the actual dispatching time.
+ optional int64 recorded_max_delay_millis = 15;
}
/**
@@ -2708,10 +2733,10 @@
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;
@@ -2770,9 +2795,9 @@
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;
}
@@ -2796,7 +2821,7 @@
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;
@@ -2806,9 +2831,9 @@
// 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;
}
@@ -2843,16 +2868,16 @@
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 5b6f167..5729feb 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 2b7da6a..4f4dd01 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 @@
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 @@
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 0000000..f566bc7
--- /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 0000000..0266d11
--- /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 0000000..ae3e5a1
--- /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 b71274c..857c390 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2791,16 +2791,6 @@
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 0000000..e69de29
--- /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 784ce04..296c063 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -22,6 +22,7 @@
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 @@
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 af8aa4e..b8fe2f1 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -45,6 +45,12 @@
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 ff6aca6..9d3c5c6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5054,7 +5054,7 @@
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 @@
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 a05d01b..a30ae79 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -431,9 +431,11 @@
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 @@
/** @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 @@
OP_CAMERA,
// Body sensors
OP_BODY_SENSORS,
+ // Activity recognition
+ OP_ACTIVITY_RECOGNITION,
// APPOP PERMISSIONS
OP_ACCESS_NOTIFICATIONS,
@@ -819,6 +826,7 @@
OP_START_FOREGROUND, // START_FOREGROUND
OP_COARSE_LOCATION, // BLUETOOTH_SCAN
OP_USE_BIOMETRIC, // BIOMETRIC
+ OP_ACTIVITY_RECOGNITION, // ACTIVITY_RECOGNITION
};
/**
@@ -904,6 +912,7 @@
OPSTR_START_FOREGROUND,
OPSTR_BLUETOOTH_SCAN,
OPSTR_USE_BIOMETRIC,
+ OPSTR_ACTIVITY_RECOGNITION,
};
/**
@@ -990,6 +999,7 @@
"START_FOREGROUND",
"BLUETOOTH_SCAN",
"USE_BIOMETRIC",
+ "ACTIVITY_RECOGNITION",
};
/**
@@ -1077,6 +1087,7 @@
Manifest.permission.FOREGROUND_SERVICE,
null, // no permission for OP_BLUETOOTH_SCAN
Manifest.permission.USE_BIOMETRIC,
+ Manifest.permission.ACTIVITY_RECOGNITION,
};
/**
@@ -1164,6 +1175,7 @@
null, // START_FOREGROUND
null, // maybe should be UserManager.DISALLOW_SHARE_LOCATION, //BLUETOOTH_SCAN
null, // USE_BIOMETRIC
+ null, // ACTIVITY_RECOGNITION
};
/**
@@ -1250,6 +1262,7 @@
false, // START_FOREGROUND
true, // BLUETOOTH_SCAN
false, // USE_BIOMETRIC
+ false, // ACTIVITY_RECOGNITION
};
/**
@@ -1335,6 +1348,7 @@
AppOpsManager.MODE_ALLOWED, // START_FOREGROUND
AppOpsManager.MODE_ALLOWED, // BLUETOOTH_SCAN
AppOpsManager.MODE_ALLOWED, // USE_BIOMETRIC
+ AppOpsManager.MODE_ALLOWED, // ACTIVITY_RECOGNITION
};
/**
@@ -1424,6 +1438,7 @@
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 264029b..fcd9a05 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -55,6 +55,7 @@
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.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 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 77f6395..dc707e8 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2088,8 +2088,7 @@
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 @@
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 @@
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 @@
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 @@
}
@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 b57a7d9..4f41da6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -20,6 +20,7 @@
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.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 @@
* @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 @@
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 @@
: 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 @@
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 @@
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 0044005..77cebc8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -377,11 +377,15 @@
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/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index df27d58..c983d4f 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -29,6 +29,7 @@
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -222,6 +223,18 @@
}
/**
+ * Provided as a convenience for agent implementations that need an opportunity
+ * to do one-time initialization before the actual backup or restore operation
+ * is begun with information about the calling user.
+ * <p>
+ *
+ * @hide
+ */
+ public void onCreate(UserHandle user) {
+ onCreate();
+ }
+
+ /**
* Provided as a convenience for agent implementations that need to do some
* sort of shutdown process after backup or restore is completed.
* <p>
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index db4adcf..3197352 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4982,6 +4982,14 @@
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 c5dce017..bfad2b4 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -921,6 +921,14 @@
* @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 6a20c93..4a4de51 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.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 @@
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 00aa5c2..cdb7814 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.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 @@
* 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 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 @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 @@
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 @@
@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);
+ return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM
+ | SAFE_STRING_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);
- }
- }
-
- /**
- * Load, clean up and truncate label before use.
+ * Calls {@link TextUtils#makeSafeForPresentation} for the label of this item.
*
- * <p>This method is meant to remove common mistakes and nefarious formatting from strings that
- * are used in sensitive parts of the UI.
+ * <p>For parameters see {@link TextUtils#makeSafeForPresentation}.
*
- * <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
* @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 733fbe5..dfb8128 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5664,7 +5664,7 @@
* {@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 @@
* 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 7b4c6fc..4f58321 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -267,14 +267,15 @@
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 248d523..e21c33a 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -33,6 +33,7 @@
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 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 @@
installReason = PackageManager.INSTALL_REASON_UNKNOWN;
}
+ @VisibleForTesting
public PackageUserState(PackageUserState o) {
ceDataInode = o.ceDataInode;
installed = o.installed;
@@ -87,7 +89,7 @@
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 @@
|| !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 0000000..5e711cf
--- /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 0000000..c798c99
--- /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 09113e5..01ef58e 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -397,7 +397,7 @@
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/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c496ff4a..1fbfa40 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2731,7 +2731,10 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK})
@SystemApi
public void setAirplaneMode(boolean enable) {
try {
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 5f65620..df3aae2 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -55,7 +55,7 @@
* Set up GraphicsEnvironment
*/
public void setup(Context context, Bundle coreSettings) {
- setupGpuLayers(context);
+ setupGpuLayers(context, coreSettings);
setupAngle(context, coreSettings);
chooseDriver(context);
}
@@ -81,27 +81,54 @@
}
/**
+ * 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 @@
// 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 @@
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 20ca19b..c9c4205 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -388,10 +388,10 @@
/**
* 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 @@
/**
* 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 8123744..7ea2008 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2363,7 +2363,6 @@
*/
@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 acb7577..c6e4574 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11631,6 +11631,12 @@
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 c89617f..0808cdd 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -23,6 +23,7 @@
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 @@
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 @@
* 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 @@
* 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 @@
/**
* 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 9bf8cd2..0a2d65c 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -22,6 +22,7 @@
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 @@
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 @@
mWidths.clear();
mFontMetrics.clear();
mSpanEndCache.clear();
- mNativeMeasuredParagraph = null;
+ mMeasuredText = null;
}
/**
@@ -245,8 +246,8 @@
* 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 @@
* @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 @@
return r;
} else {
// We have result in native.
- return mNativeMeasuredParagraph.getWidth(start, end);
+ return mMeasuredText.getWidth(start, end);
}
}
@@ -281,7 +282,7 @@
*/
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 @@
* 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 @@
@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 @@
mt.mSpanEndCache.append(spanEnd);
}
}
- mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation,
- computeLayout);
+ mt.mMeasuredText = builder.build();
}
return mt;
@@ -490,7 +491,7 @@
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 @@
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 @@
@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 @@
* 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 bfdccca..0000000
--- 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 d2f0853..2cf0262 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -22,6 +22,7 @@
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 @@
*
* - 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 @@
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 @@
.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 @@
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 @@
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 e31e928..195de07 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.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.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 @@
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 @@
/** @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 @@
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 @@
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 9c7859f..5a55fd7 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 209451b..cd2b6ce 100644
--- a/core/java/android/util/proto/ProtoInputStream.java
+++ b/core/java/android/util/proto/ProtoInputStream.java
@@ -737,8 +737,7 @@
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 @@
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 29d3742..cc58b89 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -24192,7 +24192,7 @@
* </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 @@
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 982737a..c1e94d8 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1085,6 +1085,19 @@
*
* <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 @@
* @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 742df5e8..2d77cb4 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1670,7 +1670,7 @@
*/
@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 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 @@
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 ca2ccaf..e8e4b4ab 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -48,6 +48,7 @@
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 @@
* @hide
*/
public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
- getInstanceInternal();
+ forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
}
private static final Object sLock = new Object();
@@ -279,6 +280,17 @@
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 @@
// 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 @@
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 @@
});
}
- 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 @@
* 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 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 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 @@
* 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 @@
* {@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 @@
* @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 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 @@
* 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 @@
*/
@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 @@
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 @@
* @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 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 @@
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 35ff6cc2..8f17e96 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -42,6 +42,7 @@
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 @@
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 @@
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 @@
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 @@
/**
* @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 10cf702..c256d57 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -137,7 +137,7 @@
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 a8edfb6..498de53 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 @@
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 @@
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 @@
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 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 8751517..3b7ce0a 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -1387,7 +1387,7 @@
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 @@
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 5f1243f..dceacda 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -31,7 +31,8 @@
* 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 101fd41..ec8e8da 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -51,6 +51,9 @@
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 @@
* 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 @@
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 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 c2ca2fc..ed6445d 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -84,8 +84,6 @@
"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 @@
"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 6b55ed6..c05bad2 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -145,6 +145,8 @@
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_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 @@
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 @@
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
similarity index 96%
rename from core/jni/android_text_LineBreaker.cpp
rename to core/jni/android/graphics/text/LineBreaker.cpp
index 5439107..e1f2f2b 100644
--- a/core/jni/android_text_LineBreaker.cpp
+++ b/core/jni/android/graphics/text/LineBreaker.cpp
@@ -168,8 +168,9 @@
{"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
similarity index 91%
rename from core/jni/android_text_MeasuredParagraph.cpp
rename to core/jni/android/graphics/text/MeasuredText.cpp
index 18f509c..0bfadb4 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 @@
}
// 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 @@
{"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 @@
{"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 b70485d..92235ad 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 @@
}
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 ecad6c0..d023d22 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 @@
// Class state.
jclass mClass;
jmethodID mExecTransact;
+ jmethodID mGetInterfaceDescriptor;
// Object state.
jfieldID mObject;
@@ -326,8 +328,32 @@
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 @@
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 @@
private:
JavaVM* const mVM;
jobject const mObject; // GlobalRef to Java Binder
+
+ mutable std::once_flag mPopulateDescriptor;
+ mutable String16 mDescriptor;
};
// ----------------------------------------------------------------------------
@@ -926,6 +955,8 @@
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 a02602e..47dbc07 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -397,9 +397,10 @@
// 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 d24b002..1ae5f03 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 900ca2d..dd79a0b 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 b4e26483..5cb93eb 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 3a0912b..01b0866 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 aeeba59..7b01e8a 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 2e42e4a..9551718 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 6f28b2c..97bfcc1 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 307e2e8..041fb7e 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -47,7 +47,6 @@
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 0000000..c8a30986
--- /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 60abd94..632c37f 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -450,6 +450,7 @@
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 f3d6013..3d15eb9 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -73,7 +73,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0885a05..ea0a109 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -549,7 +549,7 @@
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 fb30ca2..4de7ca7 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -520,7 +520,7 @@
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 b65fb9c..2e1d81a 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -472,8 +472,8 @@
* <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 @@
"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
similarity index 67%
rename from core/java/android/text/NativeLineBreaker.java
rename to graphics/java/android/graphics/text/LineBreaker.java
index 94e10e8..8d38f961 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.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 @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 @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 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 @@
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 @@
/**
* 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 @@
/**
* 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 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
/**
* 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 @@
*
* @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 @@
*
* @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 @@
*
* @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 @@
*
* @see #setIndent(float, int)
*/
- public @IntRange(from = 0) int getFirstWidthLineCount() {
+ public @Px @IntRange(from = 0) int getFirstWidthLineCount() {
return mFirstWidthLineCount;
}
@@ -251,13 +326,14 @@
*
* @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 @@
}
/**
- * Returns a number of line count.
+ * Returns the number of lines in the paragraph.
*
* @return number of lines
*/
@@ -283,7 +359,7 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
*
* @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 @@
}
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 @@
* @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 0000000..36e7028
--- /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 8f58f74..66a5477 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -39,7 +39,7 @@
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 69702e3..db2d038 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 @@
// 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 03154d0..c221e3b 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 bc742b0..df5f456 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -35,23 +35,6 @@
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 5604ffd..084b204 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -461,12 +461,12 @@
@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 a7eb30d..0c1d1a2 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 b52da36..352df81 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -974,15 +974,15 @@
}
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 @@
{"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/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 8c29a25..441dbac 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 @@
@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 7306d968..e407d72 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 @@
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 0f02abd..0748192 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 b87c9e8..e278c10a 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 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 af30425..cbebbb3 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 e1f6cdf..5dbcb79 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 f57122e..1457fcf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -58,7 +58,7 @@
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 3102239..3c45112 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.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 @@
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 @@
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/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4aca2bb..7124096 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -267,8 +267,10 @@
cachedDevice = mDeviceManager.addDevice(device);
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ cachedDevice);
- } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
- // Dispatch device add callback to show bonded BT device in discovery mode
+ } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
+ &&!cachedDevice.getDevice().isConnected()) {
+ // Dispatch device add callback to show bonded but
+ // not connected devices in discovery mode
dispatchDeviceAdded(cachedDevice);
}
cachedDevice.setRssi(rssi);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 750a843..a2e30df 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 @@
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 1091e16..36b70df 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 @@
@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 01f0d78..a92a2dd 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 @@
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 @@
@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 8745a33..da1354b 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 @@
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 dcc6cba..822c39b 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 5a28a5e..7c8c23e 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 @@
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 198a4e6..b1463a3 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -143,9 +143,6 @@
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 @@
if (newHeight != mOldHeight) {
animateChild(mOldHeight, newHeight);
}
+
+ post(() -> updatePaddingAndGravityIfTooTall());
post(() -> updatePosition());
}
@@ -241,7 +240,7 @@
separatedViewLayoutParams.gravity = rotateGravityRight(separatedViewLayoutParams.gravity);
mSeparatedView.setLayoutParams(separatedViewLayoutParams);
- setGravity(p.gravity);
+ setGravity(rotateGravityRight(getGravity()));
}
private void swapDimens(View v) {
@@ -299,7 +298,7 @@
separatedViewLayoutParams.gravity = rotateGravityLeft(separatedViewLayoutParams.gravity);
mSeparatedView.setLayoutParams(separatedViewLayoutParams);
- setGravity(p.gravity);
+ setGravity(rotateGravityLeft(getGravity()));
}
private int rotateGravityLeft(int gravity) {
@@ -447,6 +446,46 @@
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 d351c4f3..1bf8750 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -259,6 +259,7 @@
@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 @@
}
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 6d79066..449ed8c 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 @@
.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 4a67868..df76315 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 @@
((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 774567e..95029c0 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 @@
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 @@
@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 2c384d0..21a33b0 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 @@
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 0c5f391..a00eac4 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 @@
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 @@
private final DevicePolicyManager mDevicePolicyManager;
private boolean mDozing;
+ private float mDarkAmount;
/**
* Creates a new KeyguardIndicationController and registers callbacks.
@@ -298,6 +299,15 @@
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 @@
}
}
+ 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 @@
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 e89e6e8..2db9945 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 @@
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 d6719f0..78a5817 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.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 @@
= (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 @@
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 @@
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,16 +177,6 @@
return StatusBarState.toShortString(state);
}
- public interface StateListener {
- public default void onStatePreChange(int oldState, int newState) {
- }
-
- public default void onStatePostChange() {
- }
-
- public void onStateChanged(int newState);
- }
-
private class RankedListener {
private final StateListener listener;
private final int rank;
@@ -163,4 +186,40 @@
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);
+
+ /**
+ * 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 d097c8e..fbf12ed 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.ArraySet;
import android.view.View;
import android.widget.ImageView;
-import android.widget.RemoteViews;
import androidx.annotation.Nullable;
@@ -102,11 +101,6 @@
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 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 a3e982e..28d339a 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 @@
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.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 @@
}
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 @@
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 bce613a..23492aa 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.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,15 +437,62 @@
}
}
- 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;
- mNotificationInflater.inflateNotificationViews();
-
cacheIsSystemNotification();
}
/**
+ * Inflate views based off the inflation flags set. Inflation happens asynchronously.
+ */
+ public void inflateViews() {
+ mNotificationInflater.inflateNotificationViews();
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
* Caches whether or not this row contains a system notification. Note, this is only cached
* once per notification as the packageInfo can't technically change for a notification row.
*/
@@ -581,7 +636,7 @@
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 @@
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 4ef8dbb..7856451 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.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 @@
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 @@
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 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 @@
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 aa4765a..ea1892b 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.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 @@
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 @@
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 @@
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 @@
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 @@
}
@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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
@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 @@
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 @@
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 @@
onViewApplied(newView);
} catch (Exception anotherException) {
runningInflations.remove(inflationId);
- handleInflationError(runningInflations, e, entry.notification, callback);
+ handleInflationError(runningInflations, e, row.getStatusBarNotification(),
+ callback);
}
}
};
@@ -430,8 +566,9 @@
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 @@
*
* @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 @@
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 @@
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 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 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 @@
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 @@
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 @@
}
@VisibleForTesting
+ @InflationFlag
public int getReInflateFlags() {
return mReInflateFlags;
}
@@ -642,10 +786,9 @@
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 @@
@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 @@
}
@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 2ca7282..f76284d 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 @@
}
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 ae1353d..072343a 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 @@
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 6bccf31..99a2cdc 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 @@
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 c4efa94..980ba87 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 @@
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 56bef2e..3bdd601 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 @@
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 @@
}
@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 @@
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 57c7e28..0d37b55 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 @@
}
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 d477587..b4d24d16 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 @@
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/tuner/TunablePadding.java b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
index af99236..e85dee8 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
@@ -51,7 +51,9 @@
public void onTuningChanged(String key, String newValue) {
int dimen = mDefaultSize;
if (newValue != null) {
- dimen = (int) (Integer.parseInt(newValue) * mDensity);
+ try {
+ dimen = (int) (Integer.parseInt(newValue) * mDensity);
+ } catch (NumberFormatException ex) {}
}
int left = mView.isLayoutRtl() ? FLAG_END : FLAG_START;
int right = mView.isLayoutRtl() ? FLAG_START : FLAG_END;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 66d5ee1..4102e63 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 @@
@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 4810b0b..7abac00 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 @@
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 bdd05c7..aae6d93c 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.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 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 @@
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 @@
@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 @@
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 @@
});
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 edf29ac..aca1f90 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.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 @@
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 @@
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 @@
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 4e16b7f..f01ae7a 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.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 @@
}
@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 @@
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 @@
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 @@
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 @@
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 743b307..cfc7526 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 @@
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.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 @@
}
@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 81e79d1..150d933 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.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 @@
}
@Override
- public void onAsyncInflationFinished(NotificationData.Entry entry) {
+ public void onAsyncInflationFinished(NotificationData.Entry entry,
+ @NotificationInflater.InflationFlag int inflatedFlags) {
}
});
}
@@ -91,7 +96,7 @@
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 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 @@
}
@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 @@
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 @@
}
@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 @@
/* 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 @@
}
@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 f7a7e04..de26c70 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 @@
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 da52d40..39866a7 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.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 @@
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 328f8f7..4168a3f 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -207,7 +207,7 @@
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/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 1b97926..eb31e78 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.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 @@
// 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 @@
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 @@
// 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 @@
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 @@
}
// Cancel all running backups.
- @Override
public void cancelBackups() {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "cancelBackups");
if (MORE_DEBUG) {
@@ -1732,7 +1725,6 @@
}
}
- @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 @@
}
// synchronous waiter case
- @Override
public boolean waitUntilOperationComplete(int token) {
if (MORE_DEBUG) {
Slog.i(TAG, "Blocking until operation complete for "
@@ -1895,7 +1886,6 @@
}
- @Override
public void tearDownAgentAndKill(ApplicationInfo app) {
if (app == null) {
// Null means the system package, so just quietly move on. :)
@@ -2049,7 +2039,6 @@
* @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 @@
// 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 @@
// ----- IBackupManager binder interface -----
- @Override
public void dataChanged(final String packageName) {
final int callingUserHandle = UserHandle.getCallingUserId();
if (callingUserHandle != UserHandle.USER_SYSTEM) {
@@ -2362,7 +2349,6 @@
}
// 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 @@
}
// 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 @@
// 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 @@
//
// 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 @@
}
}
- @Override
public void fullTransportBackup(String[] pkgNames) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
"fullTransportBackup");
@@ -2618,7 +2600,6 @@
}
}
- @Override
public void adbRestore(ParcelFileDescriptor fd) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore");
@@ -2719,7 +2700,6 @@
// 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 @@
}
// Enable/disable backups
- @Override
public void setBackupEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"setBackupEnabled");
@@ -2887,7 +2866,6 @@
}
// 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 @@
}
// 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 @@
}
// Report whether the backup mechanism is currently enabled
- @Override
public boolean isBackupEnabled() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"isBackupEnabled");
@@ -2925,7 +2901,6 @@
}
// Report the name of the currently active transport
- @Override
public String getCurrentTransport() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"getCurrentTransport");
@@ -2938,7 +2913,6 @@
* 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 @@
}
// Report all known, available backup transports
- @Override
public String[] listAllTransports() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"listAllTransports");
@@ -2962,14 +2935,12 @@
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 @@
* @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 @@
}
/** Selects transport {@code transportName} and returns previous selected transport. */
- @Override
@Deprecated
@Nullable
public String selectBackupTransport(String transportName) {
@@ -3089,7 +3058,6 @@
}
}
- @Override
public void selectBackupTransportAsync(
ComponentName transportComponent, ISelectBackupTransportCallback listener) {
mContext.enforceCallingOrSelfPermission(
@@ -3161,7 +3129,6 @@
// 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 @@
* @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 @@
}
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
}
// 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 @@
// 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 @@
}
}
- @Override
public boolean isAppEligibleForBackup(String packageName) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BACKUP, "isAppEligibleForBackup");
@@ -3490,7 +3448,6 @@
}
}
- @Override
public String[] filterAppsEligibleForBackup(String[] packages) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BACKUP, "filterAppsEligibleForBackup");
@@ -3517,7 +3474,6 @@
}
}
- @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
@@ -3667,7 +3623,6 @@
}
- @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 a38a0e9..0000000
--- 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 fbec5cb..bb14576 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 @@
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 @@
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 787d667..818154b 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 @@
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 @@
BACKUP_SUPPRESS_FILENAME);
}
- protected BackupManagerServiceInterface createBackupManagerService() {
+ protected BackupManagerService createBackupManagerService() {
return BackupManagerService.create(mContext, this, mHandlerThread);
}
@@ -135,7 +135,7 @@
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 @@
@Override
public void dataChanged(String packageName) throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.dataChanged(packageName);
}
@@ -207,7 +207,7 @@
@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 @@
@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 @@
@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 @@
@Override
public void agentDisconnected(String packageName) throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.agentDisconnected(packageName);
}
@@ -240,7 +240,7 @@
@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 @@
@Override
public void setBackupEnabled(boolean isEnabled) throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.setBackupEnabled(isEnabled);
}
@@ -256,7 +256,7 @@
@Override
public void setAutoRestore(boolean doAutoRestore) throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.setAutoRestore(doAutoRestore);
}
@@ -264,7 +264,7 @@
@Override
public void setBackupProvisioned(boolean isProvisioned) throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.setBackupProvisioned(isProvisioned);
}
@@ -272,25 +272,25 @@
@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 @@
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 @@
@Override
public void fullTransportBackup(String[] packageNames) throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.fullTransportBackup(packageNames);
}
@@ -318,7 +318,7 @@
@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 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 @@
@Override
public String getCurrentTransport() throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getCurrentTransport() : null;
}
@@ -348,25 +348,25 @@
@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 @@
String currentDestinationString,
@Nullable Intent dataManagementIntent,
String dataManagementLabel) {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.updateTransportAttributes(
transportComponent,
@@ -392,14 +392,14 @@
@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 @@
@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 @@
@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 @@
@Override
public void cancelBackups() throws RemoteException {
- BackupManagerServiceInterface svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.cancelBackups();
}
@@ -492,7 +492,7 @@
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 @@
// 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 4b77c69..b750d79 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1679,6 +1679,16 @@
"ConnectivityService");
}
+ private void enforceAnyPermissionOf(String... permissions) {
+ for (String permission : permissions) {
+ if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
+ return;
+ }
+ }
+ throw new SecurityException(
+ "Requires one of the following permissions: " + String.join(", ", permissions) + ".");
+ }
+
private void enforceInternetPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERNET,
@@ -1723,6 +1733,13 @@
"ConnectivityService");
}
+ private void enforceNetworkStackSettingsOrSetup() {
+ enforceAnyPermissionOf(
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK);
+ }
+
private boolean checkNetworkStackPermission() {
return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
android.Manifest.permission.NETWORK_STACK);
@@ -3478,7 +3495,7 @@
ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
if (!ProxyTracker.proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
- mProxyTracker.sendProxyBroadcast(mProxyTracker.getDefaultProxy());
+ mProxyTracker.sendProxyBroadcast();
}
}
@@ -3984,7 +4001,7 @@
@Override
public void setAirplaneMode(boolean enable) {
- enforceConnectivityInternalPermission();
+ enforceNetworkStackSettingsOrSetup();
final long ident = Binder.clearCallingIdentity();
try {
final ContentResolver cr = mContext.getContentResolver();
@@ -4765,15 +4782,14 @@
}
}
- 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;
}
/**
@@ -4846,9 +4862,9 @@
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 26421a2..0b30ff5c 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -242,11 +242,9 @@
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 @@
static class Injector {
private final Context mContext;
+ private ConnectivityService mConnectivityService;
+ private LocationManager mLocationManager;
Injector(Context ctx) {
mContext = ctx;
@@ -1527,7 +1527,11 @@
}
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 @@
}
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 @@
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 @@
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 @@
}
}
+ @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 @@
/** 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 @@
*/
@VisibleForTesting
void setLightStateForTest(int lightState) {
- mLightState = lightState;
+ synchronized (this) {
+ mLightState = lightState;
+ }
}
@VisibleForTesting
@@ -2429,12 +2447,6 @@
}
}
- /** Must only be used in tests. */
- @VisibleForTesting
- void setLocationManagerForTest(LocationManager lm) {
- mLocationManager = lm;
- }
-
@VisibleForTesting
int getState() {
return mState;
@@ -2486,18 +2498,19 @@
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 @@
/** 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 @@
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 cf39e95..f510d83 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -170,19 +170,6 @@
*/
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 @@
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 @@
@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 @@
@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 @@
}
@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 @@
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 @@
@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 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());
- if (routeInfo.hasGateway()) {
- cmd.appendArg(routeInfo.getGateway().getHostAddress());
- }
+ final String ifName = routeInfo.getInterface();
+ final String dst = la.toString();
+ final String nextHop;
+ if (routeInfo.hasGateway()) {
+ 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 @@
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 @@
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 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 @@
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 @@
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 @@
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 8e64b50..f4ec1f9 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.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 @@
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 @@
}
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 @@
"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 @@
}
}
}
- 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 @@
}
}
- 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 @@
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 @@
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 @@
}
}
- 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 95a8e2a..fecb573 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.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 @@
*/
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 3a0289c..5c77f0a 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 @@
// 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 0e63d0c..0aaea2f 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 @@
// 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 acf7a73..d5b618f 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.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_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_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_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.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.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.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 @@
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 @@
// 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 @@
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 @@
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 @@
@GuardedBy("this") boolean mCallFinishBooting = false;
@GuardedBy("this") boolean mBootAnimationComplete = false;
- private @GuardedBy("this") boolean mCheckedForSetup = false;
final Context mContext;
@@ -1405,7 +1392,6 @@
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 @@
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 @@
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 @@
@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 @@
}
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 void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) {
mUsageStatsService = usageStatsManager;
+ mActivityTaskManager.setUsageStatsManager(usageStatsManager);
}
public void startObservingNativeCrashes() {
@@ -2297,7 +2263,6 @@
mInjector = injector;
mContext = mInjector.getContext();
mUiContext = null;
- GL_ES_VERSION = 0;
mAppErrors = null;
mAppOpsService = mInjector.getAppOpsService(null, null);
mBatteryStatsService = null;
@@ -2387,9 +2352,6 @@
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 @@
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 @@
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 @@
}
}
- boolean getCheckedForSetup() {
- return mCheckedForSetup;
- }
-
- void setCheckedForSetup(boolean checked) {
- mCheckedForSetup = checked;
- }
-
CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
return mAtmInternal.compatibilityInfoForPackage(ai);
}
@@ -3764,7 +3719,7 @@
"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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
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 @@
}
}
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 @@
}
}
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
}
}
- 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 @@
}
}
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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
}
}
- if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
+ if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
numTrimming++;
}
@@ -19212,7 +19165,7 @@
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 @@
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 @@
}
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 @@
} catch (RemoteException e) {
}
}
- app.pendingUiClean = false;
+ app.setPendingUiClean(false);
}
if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
try {
@@ -19290,8 +19243,8 @@
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 @@
} catch (RemoteException e) {
}
}
- app.pendingUiClean = false;
+ app.setPendingUiClean(false);
}
app.trimMemoryLevel = 0;
}
@@ -20320,7 +20273,7 @@
}
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 @@
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 @@
(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 40c555f8..9f768a8 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.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 7080e2b..2620e1e 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_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 @@
*/
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 @@
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 @@
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 @@
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 6bdceb2..d837118 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.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_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 @@
* 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 @@
}
}
- 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 @@
}
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 @@
}
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 864bf2d..d6a47d8 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 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.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 @@
*/
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 @@
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 8c8146c..3f823ae 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.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.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 @@
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 @@
}
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 @@
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 @@
}
// 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 @@
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 f6f1e55..20d5ab2 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.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 @@
* 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 @@
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 @@
*/
void startSetupActivity() {
// Only do this once per boot.
- if (mService.mAm.getCheckedForSetup()) {
+ if (mCheckedForSetup) {
return;
}
@@ -203,7 +205,7 @@
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 @@
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 4789ff3..e51824f 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.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 @@
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 33f949f..c92e48f 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.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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
|| !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 @@
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 @@
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 0000000..cf72738
--- /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 b369b71..6398680 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_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_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.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.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.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.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.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 @@
* {@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 @@
// 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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
&& 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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 6a9c887..a05fbc6 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 @@
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 @@
// 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 536f3a9..3c4ab00 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.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 @@
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 @@
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 09c152e..2ca1344 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 @@
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 e5add58..b39873f 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.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 cfe2829..28b2a42 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_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 @@
*/
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 643c922..5b31d5f 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.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 @@
* @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 a8e1ccc..98f3f95 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 3ac7885..9e7ce32 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 @@
// 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 @@
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 667d3fa..3128333 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
@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 dd13e98..57f939f 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.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 @@
* // '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 fa0cb47..1152165 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.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 @@
*/
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 fd34d18..7bd84e2 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.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 @@
* 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 05b0d59..5f59163 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.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 @@
// 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 @@
// 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 366f95a..51d86d6 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 @@
*
* @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 f6f4db6..a461d1c 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 @@
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 @@
* 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 @@
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 @@
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 @@
return mCurSchedGroup;
}
+ public void setCurrentProcState(int curProcState) {
+ mCurProcState = curProcState;
+ }
+
+ int getCurrentProcState() {
+ return mCurProcState;
+ }
+
public void setReportedProcState(int repProcState) {
mRepProcState = repProcState;
}
@@ -201,6 +233,78 @@
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 @@
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 47e85b5..15468ff 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 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 @@
*
* 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 @@
Binder.restoreCallingIdentity(token);
}
- sendProxyBroadcast(mGlobalProxy == null ? mDefaultProxy : proxyInfo);
+ sendProxyBroadcast();
}
}
@@ -296,14 +295,14 @@
&& (!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 @@
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 a9b0d5c..991ecb8 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 @@
final IInputContext inputContext;
final int uid;
final int pid;
+ final int selfReportedDisplayId;
final InputBinding binding;
final ClientDeathRecipient clientDeathRecipient;
@@ -430,16 +431,18 @@
@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 @@
* 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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
@Override
public void showInputMethodAndSubtypeEnablerFromClient(
IInputMethodClient client, String inputMethodId) {
+ // TODO(yukawa): Should we verify the display ID?
if (!calledFromValidUser()) {
return;
}
@@ -3229,6 +3275,7 @@
*/
@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 af06d15..7304f07 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.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.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 @@
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 @@
}
}
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 @@
// 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 @@
null /* broadcast permission */, null /* handler */);
}
- private void packageStateChanged() {
+ private void packageStateChanged(String serviceName) {
ApplicationInfo packageInfo = null;
boolean pluginsAvailable = false;
try {
@@ -144,17 +153,23 @@
+ " 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 33bb15f..1180af8 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.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;
@@ -12157,7 +12158,9 @@
if (mPackageListObservers.size() == 0) {
return;
}
- observers = (PackageListObserver[]) mPackageListObservers.toArray();
+ final PackageListObserver[] observerArray =
+ new PackageListObserver[mPackageListObservers.size()];
+ observers = mPackageListObservers.toArray(observerArray);
}
for (int i = observers.length - 1; i >= 0; --i) {
observers[i].onPackageAdded(packageName);
@@ -12177,7 +12180,9 @@
if (mPackageListObservers.size() == 0) {
return;
}
- observers = (PackageListObserver[]) mPackageListObservers.toArray();
+ final PackageListObserver[] observerArray =
+ new PackageListObserver[mPackageListObservers.size()];
+ observers = mPackageListObservers.toArray(observerArray);
}
for (int i = observers.length - 1; i >= 0; --i) {
observers[i].onPackageRemoved(packageName);
@@ -12712,8 +12717,8 @@
@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");
@@ -12758,7 +12763,7 @@
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));
@@ -17812,7 +17817,7 @@
false /*hidden*/,
false /*suspended*/,
null /*suspendingPackage*/,
- null /*dialogMessage*/,
+ null /*dialogInfo*/,
null /*suspendedAppExtras*/,
null /*suspendedLauncherExtras*/,
false /*instantApp*/,
@@ -22581,10 +22586,10 @@
}
@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 93729d1..e25cca4 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.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 @@
}
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 fd6aceb..3c22f07 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.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 @@
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 @@
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 @@
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 5c88e06..6a7e654 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.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 @@
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 @@
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 @@
false /*hidden*/,
false /*suspended*/,
null /*suspendingPackage*/,
- null /*dialogMessage*/,
+ null /*dialogInfo*/,
null /*suspendedAppExtras*/,
null /*suspendedLauncherExtras*/,
instantApp,
@@ -1620,7 +1626,7 @@
false /*hidden*/,
false /*suspended*/,
null /*suspendingPackage*/,
- null /*dialogMessage*/,
+ null /*dialogInfo*/,
null /*suspendedAppExtras*/,
null /*suspendedLauncherExtras*/,
false /*instantApp*/,
@@ -1730,6 +1736,7 @@
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 @@
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 @@
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 @@
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 2fac99e..7d699ce 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -1072,6 +1072,11 @@
e.writeLong(entry.totalLatencyMicros);
e.writeLong(entry.cpuUsageMicros);
e.writeBoolean(entry.isInteractive);
+ e.writeLong(entry.maxCpuUsageMicros);
+ e.writeLong(entry.maxLatencyMicros);
+ e.writeLong(entry.recordedDelayMessageCount);
+ e.writeLong(entry.delayMillis);
+ e.writeLong(entry.maxDelayMillis);
pulledData.add(e);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 5410676..b096bf2 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 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 10ba63e..8b1b327 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.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 @@
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 @@
}
@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 @@
// 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 @@
}
@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 8276952..eacbda1 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.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 @@
* 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 78c0be4..e67f8d3 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -84,7 +84,7 @@
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_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 8c02833..b83a79f 100644
--- a/services/tests/mockingservicestests/Android.mk
+++ b/services/tests/mockingservicestests/Android.mk
@@ -22,6 +22,7 @@
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 95ed00f..8afd788 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.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 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 @@
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 @@
private PowerManager.WakeLock mWakeLock;
class InjectorForTest extends DeviceIdleController.Injector {
+ ConnectivityService connectivityService;
+ LocationManager locationManager;
InjectorForTest(Context ctx) {
super(ctx);
@@ -122,18 +132,19 @@
@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 @@
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 @@
}
@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 @@
}
@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 @@
@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 @@
}
@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 @@
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 @@
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 @@
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 @@
count++;
if (count > 10) {
- fail(lightStateToString(mDeviceIdleController.getLightState()));
+ fail("Infinite loop. Check test configuration. Currently at " +
+ lightStateToString(mDeviceIdleController.getLightState()));
}
}
break;
@@ -979,6 +1248,14 @@
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 86541b9..65e4fa0 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.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 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 bac4a52..f143e35 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.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.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 @@
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 @@
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);
@@ -510,7 +513,7 @@
*/
@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);
@@ -528,7 +531,7 @@
@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 20088619..023f775 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 @@
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 79eba68..92211ec 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 @@
}
@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 c3c0788..517b5ad 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.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 @@
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 @@
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 @@
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 @@
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 4a33ca3..f0ed612 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.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 @@
public class PackageUserStateTest {
@Test
- public void testPackageUserState01() {
+ public void testPackageUserState01() {
final PackageUserState testUserState = new PackageUserState();
PackageUserState oldUserState;
@@ -84,7 +85,7 @@
}
@Test
- public void testPackageUserState02() {
+ public void testPackageUserState02() {
final PackageUserState testUserState01 = new PackageUserState();
PackageUserState oldUserState;
@@ -102,7 +103,7 @@
}
@Test
- public void testPackageUserState03() {
+ public void testPackageUserState03() {
final PackageUserState oldUserState = new PackageUserState();
// only new user state has array defined; different
@@ -138,7 +139,7 @@
}
@Test
- public void testPackageUserState04() {
+ public void testPackageUserState04() {
final PackageUserState oldUserState = new PackageUserState();
// only new user state has array defined; different
@@ -185,15 +186,19 @@
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 @@
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 0000000..7eccd67
--- /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 f115b9c..553d234a 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.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 @@
}
void drainPendingBroadcasts() {
- while (pollForIntent(5) != null);
+ while (pollForIntent(5) != null) ;
}
Intent receiveIntentFromApp() {
@@ -215,15 +216,15 @@
}
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 @@
@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 @@
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 60025f0..ae40f7e7 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 @@
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 c3e9184..3681529 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_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 0000000..7a9f41f
--- /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 0000000..d280abc
--- /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 0000000..0d8b854
--- /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 0ad7e24..7d791c2 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 @@
private:
JavaLangViewBuilder* builder_;
};
+
} // end namespace
int main(int argc, char** argv) {
@@ -82,6 +86,11 @@
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 @@
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 d33a537..3127b35 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -676,7 +676,7 @@
/**
* @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 e0ec2c5..bfbcd57 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -21,6 +21,7 @@
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 @@
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 @@
@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 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public int getVoiceRegState() {
return mVoiceRegState;
}
@@ -471,7 +472,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public int getDataRegState() {
return mDataRegState;
}
@@ -532,7 +533,7 @@
* @return roaming status
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public boolean getVoiceRoaming() {
return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
@@ -556,7 +557,7 @@
* @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 f850693..40ba2b6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1369,7 +1369,7 @@
}
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public static int getPhoneId(int subId) {
if (!isValidSubscriptionId(subId)) {
if (DBG) {
@@ -1665,7 +1665,7 @@
* 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 @@
}
/** @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 fca14c8..914ff1f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -230,7 +230,8 @@
/** @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 @@
}
/** {@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 @@
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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @see #getSimState
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getSimOperatorNumeric() {
int subId = mSubId;
if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -2820,7 +2820,7 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
/**
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
@@ -7945,7 +7945,7 @@
* 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 32eb12b..1087fce 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -280,7 +280,7 @@
/**
* 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 3bd3d68..2b968ae 100644
--- a/test-mock/api/system-current.txt
+++ b/test-mock/api/system-current.txt
@@ -29,6 +29,7 @@
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 9d260eb..fa5b896 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -774,6 +774,12 @@
/** @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 76a2f2d..710da40 100755
--- a/tools/hiddenapi/sort_api.sh
+++ b/tools/hiddenapi/sort_api.sh
@@ -21,4 +21,6 @@
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 f5cad13..0000000
--- 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];
- }
- };
-}
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index b4dfac6..6076175 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -102,6 +102,12 @@
public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14;
/**
+ * The reason code for provisioning failure when the status of a SOAP message is not the
+ * expected message status.
+ */
+ public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15;
+
+ /**
* The status code for provisioning flow to indicate connecting to OSU AP
*/
public static final int OSU_STATUS_AP_CONNECTING = 1;
@@ -147,6 +153,11 @@
public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9;
/**
+ * The status code for provisioning flow to indicate starting the third SOAP exchange.
+ */
+ public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10;
+
+ /**
* Provisioning status for OSU failure
*
* @param status indicates error condition