Merge "Listen for IFingerprintServiceLockoutResetCallback death"
diff --git a/Android.bp b/Android.bp
index 03abf75..e65ba0f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -249,8 +249,7 @@
"core/java/android/os/storage/IStorageEventListener.aidl",
"core/java/android/os/storage/IStorageShutdownObserver.aidl",
"core/java/android/os/storage/IObbActionListener.aidl",
- "core/java/android/security/IConfirmationPromptCallback.aidl",
- "core/java/android/security/IKeystoreService.aidl",
+ ":keystore_aidl",
"core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
"core/java/android/service/autofill/IAutoFillService.aidl",
"core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
@@ -643,6 +642,7 @@
"system/netd/server/binder",
"system/vold/binder",
"system/bt/binder",
+ "system/security/keystore/binder",
],
},
diff --git a/api/current.txt b/api/current.txt
index 042360e..53f503a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1468,6 +1468,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
+ field public static final int urlBarResourceId = 16844164; // 0x1010584
field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
@@ -12554,6 +12555,7 @@
method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
method public void setIdleConnectionTimeout(long);
method public void setLookasideConfig(int, int);
+ method public void setOpenParams(android.database.sqlite.SQLiteDatabase.OpenParams);
method public void setWriteAheadLoggingEnabled(boolean);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 39cbe90..5afb455 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -229,7 +229,6 @@
method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions);
method public deprecated boolean isBackgroundVisibleBehind();
method public deprecated void onBackgroundVisibleBehindChanged(boolean);
- method public void setDisablePreviewScreenshots(boolean);
}
public static abstract interface Activity.TranslucentConversionListener {
@@ -3606,11 +3605,14 @@
}
public abstract class HwBinder implements android.os.IHwBinder {
+ ctor public HwBinder();
method public static final void configureRpcThreadpool(long, boolean);
method public static void enableInstrumentation();
method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String) throws java.util.NoSuchElementException, android.os.RemoteException;
method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
method public static final void joinRpcThreadpool();
+ method public abstract void onTransact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
+ method public final void registerService(java.lang.String) throws android.os.RemoteException;
method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
}
diff --git a/api/test-current.txt b/api/test-current.txt
index b02da04..eda6296 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1047,6 +1047,15 @@
}
+package android.view.animation {
+
+ public class AnimationUtils {
+ method public static void lockAnimationClock(long);
+ method public static void unlockAnimationClock();
+ }
+
+}
+
package android.view.autofill {
public final class AutofillId implements android.os.Parcelable {
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 67b9089..740fdc0 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -116,10 +116,8 @@
LOCAL_CFLAGS += \
-Wall \
+ -Wextra \
-Werror \
- -Wno-missing-field-initializers \
- -Wno-unused-variable \
- -Wno-unused-function \
-Wno-unused-parameter
ifeq (debug,)
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 7b0b69a..6894bcf 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -23,6 +23,23 @@
namespace os {
namespace statsd {
+int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth) {
+ int32_t field = 0;
+ for (int32_t i = 0; i <= depth; i++) {
+ int32_t shiftBits = 8 * (kMaxLogDepth - i);
+ field |= (pos[i] << shiftBits);
+ }
+
+ if (includeDepth) {
+ field |= (depth << 24);
+ }
+ return field;
+}
+
+int32_t encodeMatcherMask(int32_t mask[], int32_t depth) {
+ return getEncodedField(mask, depth, false) | 0xff000000;
+}
+
bool Field::matches(const Matcher& matcher) const {
if (mTag != matcher.mMatcher.getTag()) {
return false;
@@ -32,7 +49,7 @@
}
return false;
-};
+}
void translateFieldMatcher(int tag, const FieldMatcher& matcher, int depth, int* pos, int* mask,
std::vector<Matcher>* output) {
@@ -71,7 +88,6 @@
if (matcher.child_size() == 0) {
output->push_back(Matcher(Field(tag, pos, depth), encodeMatcherMask(mask, depth)));
- Matcher matcher = Matcher(Field(tag, pos, depth), encodeMatcherMask(mask, depth));
} else {
for (const auto& child : matcher.child()) {
translateFieldMatcher(tag, child, depth + 1, pos, mask, output);
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 7484108..d17dded 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -33,29 +33,14 @@
enum Type { INT, LONG, FLOAT, STRING };
+int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth);
-static int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth) {
- int32_t field = 0;
- for (int32_t i = 0; i <= depth; i++) {
- int32_t shiftBits = 8 * (kMaxLogDepth - i);
- field |= (pos[i] << shiftBits);
- }
-
- if (includeDepth) {
- field |= (depth << 24);
- }
- return field;
-}
-
-static int32_t encodeMatcherMask(int32_t mask[], int32_t depth) {
- return getEncodedField(mask, depth, false) | 0xff000000;
-}
+int32_t encodeMatcherMask(int32_t mask[], int32_t depth);
// Get the encoded field for a leaf with a [field] number at depth 0;
-static int32_t getSimpleField(size_t field) {
+inline int32_t getSimpleField(size_t field) {
return ((int32_t)field << 8 * 2);
}
-
/**
* Field is a wrapper class for 2 integers that represents the field of a log element in its Atom
* proto.
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index 68e2176..d901bd6 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -68,7 +68,6 @@
for (const auto& value : values) {
// TODO: potential optimization here to break early because all fields are naturally
// sorted.
- int32_t filteredField;
if (value.mField.matches(matcher)) {
matchedResults.push_back(FieldValue(
Field(value.mField.getTag(), (value.mField.getField() & matcher.mMask)),
@@ -148,7 +147,6 @@
const std::vector<FieldValue>& values, std::vector<FieldValue>* output) {
for (const auto& field : matcherFields) {
for (const auto& value : values) {
- int filteredField;
if (value.mField.matches(field)) {
output->push_back(value);
}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index afb2c47..87dec5d 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -58,7 +58,7 @@
const int FIELD_ID_UID = 1;
const int FIELD_ID_ID = 2;
// for ConfigMetricsReport
-const int FIELD_ID_METRICS = 1;
+// const int FIELD_ID_METRICS = 1; // written in MetricsManager.cpp
const int FIELD_ID_UID_MAP = 2;
const int FIELD_ID_LAST_REPORT_ELAPSED_NANOS = 3;
const int FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS = 4;
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index bb47653..0a4e412 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -124,8 +124,6 @@
*/
status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
- status_t err;
-
switch (code) {
case SHELL_COMMAND_TRANSACTION: {
int in = data.readFileDescriptor();
@@ -240,8 +238,8 @@
return cmd_write_data_to_disk(out);
}
- if (!args[0].compare(String8("log-app-hook"))) {
- return cmd_log_app_hook(out, args);
+ if (!args[0].compare(String8("log-app-breadcrumb"))) {
+ return cmd_log_app_breadcrumb(out, args);
}
if (!args[0].compare(String8("clear-puller-cache"))) {
@@ -284,8 +282,8 @@
fprintf(out, " Flushes all data on memory to disk.\n");
fprintf(out, "\n");
fprintf(out, "\n");
- fprintf(out, "usage: adb shell cmd stats log-app-hook [UID] LABEL STATE\n");
- fprintf(out, " Writes an AppHook event to the statslog buffer.\n");
+ fprintf(out, "usage: adb shell cmd stats log-app-breadcrumb [UID] LABEL STATE\n");
+ fprintf(out, " Writes an AppBreadcrumbReported event to the statslog buffer.\n");
fprintf(out, " UID The uid to use. It is only possible to pass a UID\n");
fprintf(out, " parameter on eng builds. If UID is omitted the calling\n");
fprintf(out, " uid is used.\n");
@@ -551,7 +549,7 @@
return NO_ERROR;
}
-status_t StatsService::cmd_log_app_hook(FILE* out, const Vector<String8>& args) {
+status_t StatsService::cmd_log_app_breadcrumb(FILE* out, const Vector<String8>& args) {
bool good = false;
int32_t uid;
int32_t label;
@@ -573,13 +571,13 @@
good = true;
} else {
fprintf(out,
- "Selecting a UID for writing AppHook can only be dumped for other UIDs on eng"
+ "Selecting a UID for writing Appbreadcrumb can only be dumped for other UIDs on eng"
" or userdebug builds.\n");
}
}
if (good) {
- fprintf(out, "Logging AppHook(%d, %d, %d) to statslog.\n", uid, label, state);
- android::util::stats_write(android::util::APP_HOOK, uid, label, state);
+ fprintf(out, "Logging AppBreadcrumbReported(%d, %d, %d) to statslog.\n", uid, label, state);
+ android::util::stats_write(android::util::APP_BREADCRUMB_REPORTED, uid, label, state);
} else {
print_cmd_help(out);
return UNKNOWN_ERROR;
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 3dc19fe..fd65869 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -193,9 +193,10 @@
status_t cmd_write_data_to_disk(FILE* out);
/**
- * Write an AppHook event to the StatsLog buffer, as though StatsLog.write(APP_HOOK).
+ * Write an AppBreadcrumbReported event to the StatsLog buffer, as though StatsLog.write
+ * (APP_BREADCRUMB_REPORTED).
*/
- status_t cmd_log_app_hook(FILE* out, const Vector<String8>& args);
+ status_t cmd_log_app_breadcrumb(FILE* out, const Vector<String8>& args);
/**
* Print contents of a pulled metrics source.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4c6a36b..1224504 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -85,7 +85,7 @@
PacketWakeupOccurred packet_wakeup_occurred = 44;
DropboxErrorChanged dropbox_error_changed = 45;
AnomalyDetected anomaly_detected = 46;
- AppHook app_hook = 47;
+ AppBreadcrumbReported app_breadcrumb_reported = 47;
AppStartChanged app_start_changed = 48;
AppStartCancelChanged app_start_cancel_changed = 49;
AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50;
@@ -202,9 +202,10 @@
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message ProcessLifeCycleStateChanged {
- optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation
+ // TODO: should be a string tagged w/ uid annotation
+ optional int32 uid = 1;
- // TODO: What is this?
+ // The process name (usually same as the app name).
optional string name = 2;
// What lifecycle state the process changed to.
@@ -312,7 +313,7 @@
message SyncStateChanged {
repeated AttributionNode attribution_node = 1;
- // Name of the sync (as named in the app)
+ // Name of the sync (as named in the app). Can be chosen at run-time.
optional string name = 2;
enum State {
@@ -615,7 +616,7 @@
optional string wakeup_reason_name = 1;
// Duration (in microseconds) for the wake-up interrupt to be serviced.
- optional int64 duration_usec = 2;
+ optional int64 duration_micros = 2;
}
/**
@@ -692,10 +693,10 @@
// Beginning of shutdown time in ms using wall clock time since unix epoch.
// Default: 0 if no start time received.
- optional int64 start_time_ms = 3;
+ optional int64 start_time_millis = 3;
// Duration of shutdown in ms. Default: 0 if no duration received.
- optional int64 duration_ms = 4;
+ optional int64 duration_millis = 4;
}
@@ -715,13 +716,13 @@
optional string system_reason = 2;
// End of boot time in ms from unix epoch using system wall clock.
- optional int64 end_time_ms = 3;
+ optional int64 end_time_millis = 3;
// Total boot duration in ms.
- optional int64 total_duration_ms = 4;
+ optional int64 total_duration_millis = 4;
// Bootloader duration in ms.
- optional int64 bootloader_duration_ms = 5;
+ optional int64 bootloader_duration_millis = 5;
// Time since last boot in ms. Default: 0 if not available.
optional int64 time_since_last_boot = 6;
@@ -762,7 +763,7 @@
*/
message DaveyOccurred {
// Amount of time it took to render the frame. Should be >=700ms.
- optional int64 jank_duration_ms = 1;
+ optional int64 jank_duration_millis = 1;
}
/**
@@ -863,7 +864,7 @@
* Logged from:
* frameworks/base/core/java/android/util/StatsLog.java
*/
-message AppHook {
+message AppBreadcrumbReported {
// The uid of the application that sent this custom atom.
optional int32 uid = 1;
@@ -924,16 +925,16 @@
optional bool is_instant_app = 6;
// Device uptime when activity started.
- optional int64 activity_start_msec = 7;
+ optional int64 activity_start_millis = 7;
optional android.app.AppTransitionReasonEnum reason = 8;
- optional int32 transition_delay_msec = 9;
+ optional int32 transition_delay_millis = 9;
// -1 if not set.
- optional int32 starting_window_delay_msec = 10;
+ optional int32 starting_window_delay_millis = 10;
// -1 if not set.
- optional int32 bind_application_delay_msec = 11;
- optional int32 windows_drawn_delay_msec = 12;
+ optional int32 bind_application_delay_millis = 11;
+ optional int32 windows_drawn_delay_millis = 12;
// Empty if not set.
optional string launch_token = 13;
@@ -981,7 +982,7 @@
optional bool transition_process_running = 5;
// App startup time (until call to Activity#reportFullyDrawn()).
- optional int64 app_startup_time_ms = 6;
+ optional int64 app_startup_time_millis = 6;
}
/**
@@ -1303,7 +1304,7 @@
// The number of times it entered, or voted for entering the sleep state
optional uint64 count = 3;
// The length of time spent in, or spent voting for, the sleep state
- optional uint64 timeMs = 4;
+ optional uint64 time_millis = 4;
}
/**
@@ -1316,7 +1317,7 @@
message CpuTimePerFreq {
optional uint32 cluster = 1;
optional uint32 freq_index = 2;
- optional uint64 time_ms = 3;
+ optional uint64 time_millis = 3;
}
/**
@@ -1325,8 +1326,8 @@
*/
message CpuTimePerUid {
optional uint64 uid = 1;
- optional uint64 user_time_ms = 2;
- optional uint64 sys_time_ms = 3;
+ optional uint64 user_time_millis = 2;
+ optional uint64 sys_time_millis = 3;
}
/**
@@ -1337,7 +1338,7 @@
message CpuTimePerUidFreq {
optional uint64 uid = 1;
optional uint64 freq_idx = 2;
- optional uint64 time_ms = 3;
+ optional uint64 time_millis = 3;
}
/**
@@ -1345,16 +1346,16 @@
*/
message WifiActivityEnergyInfo {
// timestamp(wall clock) of record creation
- optional uint64 timestamp_ms = 1;
+ optional uint64 timestamp_millis = 1;
// stack reported state
// TODO: replace this with proto enum
optional int32 stack_state = 2;
// tx time in ms
- optional uint64 controller_tx_time_ms = 3;
+ optional uint64 controller_tx_time_millis = 3;
// rx time in ms
- optional uint64 controller_rx_time_ms = 4;
+ optional uint64 controller_rx_time_millis = 4;
// idle time in ms
- optional uint64 controller_idle_time_ms = 5;
+ optional uint64 controller_idle_time_millis = 5;
// product of current(mA), voltage(V) and time(ms)
optional uint64 controller_energy_used = 6;
}
@@ -1364,11 +1365,11 @@
*/
message ModemActivityInfo {
// timestamp(wall clock) of record creation
- optional uint64 timestamp_ms = 1;
+ optional uint64 timestamp_millis = 1;
// sleep time in ms.
- optional uint64 sleep_time_ms = 2;
+ optional uint64 sleep_time_millis = 2;
// idle time in ms
- optional uint64 controller_idle_time_ms = 3;
+ optional uint64 controller_idle_time_millis = 3;
/**
* Tx power index
* index 0 = tx_power < 0dBm
@@ -1378,17 +1379,17 @@
* index 4 = tx_power > 20dBm
*/
// tx time in ms at power level 0
- optional uint64 controller_tx_time_pl0_ms = 4;
+ optional uint64 controller_tx_time_pl0_millis = 4;
// tx time in ms at power level 1
- optional uint64 controller_tx_time_pl1_ms = 5;
+ optional uint64 controller_tx_time_pl1_millis = 5;
// tx time in ms at power level 2
- optional uint64 controller_tx_time_pl2_ms = 6;
+ optional uint64 controller_tx_time_pl2_millis = 6;
// tx time in ms at power level 3
- optional uint64 controller_tx_time_pl3_ms = 7;
+ optional uint64 controller_tx_time_pl3_millis = 7;
// tx time in ms at power level 4
- optional uint64 controller_tx_time_pl4_ms = 8;
+ optional uint64 controller_tx_time_pl4_millis = 8;
// rx time in ms at power level 5
- optional uint64 controller_rx_time_ms = 9;
+ optional uint64 controller_rx_time_millis = 9;
// product of current(mA), voltage(V) and time(ms)
optional uint64 energy_used = 10;
}
@@ -1399,15 +1400,15 @@
*/
message BluetoothActivityInfo {
// timestamp(wall clock) of record creation
- optional uint64 timestamp_ms = 1;
+ optional uint64 timestamp_millis = 1;
// bluetooth stack state
optional int32 bluetooth_stack_state = 2;
// tx time in ms
- optional uint64 controller_tx_time_ms = 3;
+ optional uint64 controller_tx_time_millis = 3;
// rx time in ms
- optional uint64 controller_rx_time_ms = 4;
+ optional uint64 controller_rx_time_millis = 4;
// idle time in ms
- optional uint64 controller_idle_time_ms = 5;
+ optional uint64 controller_idle_time_millis = 5;
// product of current(mA), voltage(V) and time(ms)
optional uint64 energy_used = 6;
}
@@ -1445,7 +1446,7 @@
* Elapsed real time from SystemClock.
*/
message SystemElapsedRealtime {
- optional uint64 time_ms = 1;
+ optional uint64 time_millis = 1;
}
/*
@@ -1456,7 +1457,7 @@
// This clock stops when the system enters deep sleep (CPU off, display dark, device waiting
// for external input).
// It is not affected by clock scaling, idle, or other power saving mechanisms.
- optional uint64 uptime_ms = 1;
+ optional uint64 uptime_millis = 1;
}
/*
@@ -1470,8 +1471,9 @@
*/
message CpuActiveTime {
optional uint64 uid = 1;
- optional uint64 idx = 2;
- optional uint64 time_ms = 3;
+ optional uint32 cluster_number =2;
+ optional uint64 idx = 3;
+ optional uint64 time_millis = 4;
}
/**
@@ -1486,7 +1488,7 @@
message CpuClusterTime {
optional uint64 uid = 1;
optional uint64 idx = 2;
- optional uint64 time_ms = 3;
+ optional uint64 time_millis = 3;
}
/*
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index e2e9426..66cb1d0 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -45,18 +45,9 @@
const int FIELD_ID_ATOM_STATS = 7;
const int FIELD_ID_UIDMAP_STATS = 8;
const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
-const int FIELD_ID_PULLED_ATOM_STATS = 10;
+// const int FIELD_ID_PULLED_ATOM_STATS = 10; // The proto is written in stats_log_util.cpp
const int FIELD_ID_LOGGER_ERROR_STATS = 11;
-const int FIELD_ID_MATCHER_STATS_NAME = 1;
-const int FIELD_ID_MATCHER_STATS_COUNT = 2;
-
-const int FIELD_ID_CONDITION_STATS_NAME = 1;
-const int FIELD_ID_CONDITION_STATS_COUNT = 2;
-
-const int FIELD_ID_METRIC_STATS_NAME = 1;
-const int FIELD_ID_METRIC_STATS_COUNT = 2;
-
const int FIELD_ID_ATOM_STATS_TAG = 1;
const int FIELD_ID_ATOM_STATS_COUNT = 2;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 7489d9b..f07fc66 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -178,10 +178,6 @@
void LogEvent::init(android_log_context context) {
android_log_list_element elem;
int i = 0;
-
- int seenListStart = 0;
-
- int32_t field = 0;
int depth = -1;
int pos[] = {1, 1, 1};
do {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index af22578c..67d95db 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -150,10 +150,9 @@
std::unordered_set<HashableDimensionKey> conditionDimensionsKeySet;
- ConditionState conditionState = mWizard->getMetConditionDimension(
- mConditionTrackerIndex, mDimensionsInCondition, &conditionDimensionsKeySet);
+ mWizard->getMetConditionDimension(mConditionTrackerIndex, mDimensionsInCondition,
+ &conditionDimensionsKeySet);
- bool condition = (conditionState == ConditionState::kTrue);
for (auto& pair : mCurrentSlicedDurationTrackerMap) {
conditionDimensionsKeySet.erase(pair.first.getDimensionKeyInCondition());
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index af3b4c5..8aa8169 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -334,7 +334,6 @@
}
void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() {
- status_t err = NO_ERROR;
for (const auto& slice : *mCurrentSlicedBucket) {
if (slice.second.empty()) {
continue;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index ae48c52..66e1aeb 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -188,7 +188,7 @@
return;
}
- if (event.GetTagId() == android::util::APP_HOOK) { // Check that app hook fields are valid.
+ if (event.GetTagId() == android::util::APP_BREADCRUMB_REPORTED) { // Check that app hook fields are valid.
// TODO: Find a way to make these checks easier to maintain if the app hooks get changed.
status_t err = NO_ERROR;
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index c29876b..95df5ae6 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -177,7 +177,6 @@
false; // has either a kStarted or kPaused event across bucket boundaries
// meaning we need to carry them over to the new bucket.
for (auto it = mInfos.begin(); it != mInfos.end(); ++it) {
- int64_t finalDuration = it->second.lastDuration;
if (it->second.state == DurationState::kStopped) {
// No need to keep buckets for events that were stopped before.
mInfos.erase(it);
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index e735770..f7b768f 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -41,15 +41,12 @@
const int DIMENSIONS_VALUE_VALUE_STR = 2;
const int DIMENSIONS_VALUE_VALUE_INT = 3;
const int DIMENSIONS_VALUE_VALUE_LONG = 4;
-const int DIMENSIONS_VALUE_VALUE_BOOL = 5;
+// const int DIMENSIONS_VALUE_VALUE_BOOL = 5; // logd doesn't have bool data type.
const int DIMENSIONS_VALUE_VALUE_FLOAT = 6;
const int DIMENSIONS_VALUE_VALUE_TUPLE = 7;
const int DIMENSIONS_VALUE_TUPLE_VALUE = 1;
-// for MessageValue Proto
-const int FIELD_ID_FIELD_VALUE_IN_MESSAGE_VALUE_PROTO = 1;
-
// for PulledAtomStats proto
const int FIELD_ID_PULLED_ATOM_STATS = 10;
const int FIELD_ID_PULL_ATOM_ID = 1;
@@ -131,11 +128,6 @@
protoOutput->end(topToken);
}
-// for Field Proto
-const int FIELD_FIELD = 1;
-const int FIELD_POSITION_INDEX = 2;
-const int FIELD_CHILD = 3;
-
// Supported Atoms format
// XYZ_Atom {
// repeated SubMsg field_1 = 1;
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
index 674d810..6aa7dd6 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
@@ -161,21 +161,21 @@
EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT);
EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2");
- EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 102L);
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 102L);
EXPECT_EQ(data.bucket_info(1).atom_size(), 1);
EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM);
EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4");
- EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_msec(), 104L);
+ EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_millis(), 104L);
EXPECT_EQ(data.bucket_info(2).atom_size(), 1);
EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD);
EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5");
- EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_msec(), 105L);
+ EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_millis(), 105L);
data = gaugeMetrics.data(1);
@@ -189,7 +189,7 @@
EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD);
EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7");
- EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 201L);
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 201L);
}
#else
diff --git a/core/java/Android.bp b/core/java/Android.bp
index f7c5c57..fb27f74 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -7,33 +7,3 @@
name: "IDropBoxManagerService.aidl",
srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],
}
-
-// only used by key_store_service
-cc_library_shared {
- name: "libkeystore_aidl",
- srcs: ["android/security/IKeystoreService.aidl",
- "android/security/IConfirmationPromptCallback.aidl"],
- aidl: {
- export_aidl_headers: true,
- include_dirs: [
- "frameworks/base/core/java/",
- "system/security/keystore/",
- ],
- },
- shared_libs: [
- "libbinder",
- "libcutils",
- "libhardware",
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libkeystore_parcelables",
- "libselinux",
- "libutils",
- ],
- export_shared_lib_headers: [
- "libbinder",
- "libkeystore_parcelables",
- ],
-}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bcd88fe..3283759 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7751,7 +7751,6 @@
* @param disable {@code true} to disable preview screenshots; {@code false} otherwise.
* @hide
*/
- @SystemApi
public void setDisablePreviewScreenshots(boolean disable) {
try {
ActivityManager.getService().setDisablePreviewScreenshots(mToken, disable);
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 0f1c249..1312a2e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1303,6 +1303,17 @@
}
/**
+ * @hide
+ */
+ public void setWebDomain(@Nullable String domain) {
+ if (domain == null) return;
+
+ final Uri uri = Uri.parse(domain);
+ mWebScheme = uri.getScheme();
+ mWebDomain = uri.getHost();
+ }
+
+ /**
* Returns the scheme of the HTML document represented by this view.
*
* <p>Typically used when the view associated with the view is a container for an HTML
@@ -1889,14 +1900,7 @@
@Override
public void setWebDomain(@Nullable String domain) {
- if (domain == null) {
- mNode.mWebScheme = null;
- mNode.mWebDomain = null;
- return;
- }
- Uri uri = Uri.parse(domain);
- mNode.mWebScheme = uri.getScheme();
- mNode.mWebDomain = uri.getHost();
+ mNode.setWebDomain(domain);
}
@Override
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index a2991e6..64e9e5d 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -58,7 +58,7 @@
private SQLiteDatabase mDatabase;
private boolean mIsInitializing;
- private final SQLiteDatabase.OpenParams.Builder mOpenParamsBuilder;
+ private SQLiteDatabase.OpenParams.Builder mOpenParamsBuilder;
/**
* Create a helper object to create, open, and/or manage a database.
@@ -163,8 +163,7 @@
mName = name;
mNewVersion = version;
mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
- mOpenParamsBuilder = openParamsBuilder;
- mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
+ setOpenParamsBuilder(openParamsBuilder);
}
/**
@@ -230,6 +229,30 @@
}
/**
+ * Sets configuration parameters that are used for opening {@link SQLiteDatabase}.
+ * <p>Please note that {@link SQLiteDatabase#CREATE_IF_NECESSARY} flag will always be set when
+ * opening the database
+ *
+ * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}.
+ * @throws IllegalStateException if the database is already open
+ */
+ public void setOpenParams(@NonNull SQLiteDatabase.OpenParams openParams) {
+ Preconditions.checkNotNull(openParams);
+ synchronized (this) {
+ if (mDatabase != null && mDatabase.isOpen()) {
+ throw new IllegalStateException(
+ "OpenParams cannot be set after opening the database");
+ }
+ setOpenParamsBuilder(new SQLiteDatabase.OpenParams.Builder(openParams));
+ }
+ }
+
+ private void setOpenParamsBuilder(SQLiteDatabase.OpenParams.Builder openParamsBuilder) {
+ mOpenParamsBuilder = openParamsBuilder;
+ mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
+ }
+
+ /**
* Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
* before it is closed and removed from the pool.
*
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 3f8eaa9..8502fc4 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -341,7 +341,7 @@
*/
@SuppressWarnings({"unchecked"})
public List<CaptureRequest.Key<?>> getAvailablePhysicalCameraRequestKeys() {
- if (mAvailableSessionKeys == null) {
+ if (mAvailablePhysicalRequestKeys == null) {
Object crKey = CaptureRequest.Key.class;
Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;
@@ -1790,11 +1790,7 @@
* The respective value of such request key can be obtained by calling
* {@link CaptureRequest.Builder#getPhysicalCameraKey }. Capture requests that contain
* individual physical device requests must be built via
- * {@link android.hardware.camera2.CameraDevice#createCaptureRequest(int, Set)}.
- * Such extended capture requests can be passed only to
- * {@link CameraCaptureSession#capture } or {@link CameraCaptureSession#captureBurst } and
- * not to {@link CameraCaptureSession#setRepeatingRequest } or
- * {@link CameraCaptureSession#setRepeatingBurst }.</p>
+ * {@link android.hardware.camera2.CameraDevice#createCaptureRequest(int, Set)}.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
* Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index fd285ae..72db33f 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -863,11 +863,8 @@
* request for a specific physical camera. The settings are chosen
* to be the best options for the specific logical camera device. If
* additional physical camera ids are passed, then they will also use the
- * same settings template. Requests containing individual physical camera
- * settings can be passed only to {@link CameraCaptureSession#capture} or
- * {@link CameraCaptureSession#captureBurst} and not to
- * {@link CameraCaptureSession#setRepeatingRequest} or
- * {@link CameraCaptureSession#setRepeatingBurst}</p>
+ * same settings template. Clients can further modify individual camera
+ * settings by calling {@link CaptureRequest.Builder#setPhysicalCameraKey}.</p>
*
* <p>Individual physical camera settings will only be honored for camera session
* that was initialiazed with corresponding physical camera id output configuration
@@ -896,8 +893,8 @@
* @see #TEMPLATE_STILL_CAPTURE
* @see #TEMPLATE_VIDEO_SNAPSHOT
* @see #TEMPLATE_MANUAL
- * @see CaptureRequest.Builder#setKey
- * @see CaptureRequest.Builder#getKey
+ * @see CaptureRequest.Builder#setPhysicalCameraKey
+ * @see CaptureRequest.Builder#getPhysicalCameraKey
*/
@NonNull
public CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType,
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index cdee110..228fe7a 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -29,7 +29,13 @@
private static final NativeAllocationRegistry sNativeRegistry;
- /** @hide */
+ /**
+ * Create and initialize a HwBinder object and the native objects
+ * used to allow this to participate in hwbinder transactions.
+ *
+ * @hide
+ */
+ @SystemApi
public HwBinder() {
native_setup();
@@ -44,12 +50,28 @@
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;
- /** @hide */
+ /**
+ * Process a hwbinder transaction.
+ *
+ * @param code interface specific code for interface.
+ * @param request parceled transaction
+ * @param reply object to parcel reply into
+ * @param flags transaction flags to be chosen by wire protocol
+ *
+ * @hide
+ */
+ @SystemApi
public abstract void onTransact(
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;
- /** @hide */
+ /**
+ * Registers this service with the hwservicemanager.
+ *
+ * @param serviceName instance name of the service
+ * @hide
+ */
+ @SystemApi
public native final void registerService(String serviceName)
throws RemoteException;
diff --git a/core/java/android/security/IConfirmationPromptCallback.aidl b/core/java/android/security/IConfirmationPromptCallback.aidl
deleted file mode 100644
index 96a1a04..0000000
--- a/core/java/android/security/IConfirmationPromptCallback.aidl
+++ /dev/null
@@ -1,27 +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 android.security;
-
-/**
- * This must be kept manually in sync with system/security/keystore until AIDL
- * can generate both Java and C++ bindings.
- *
- * @hide
- */
-interface IConfirmationPromptCallback {
- oneway void onConfirmationPromptCompleted(in int result, in byte[] dataThatWasConfirmed);
-}
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
deleted file mode 100644
index 738eb68..0000000
--- a/core/java/android/security/IKeystoreService.aidl
+++ /dev/null
@@ -1,87 +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.security;
-
-import android.security.keymaster.ExportResult;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterBlob;
-import android.security.keymaster.OperationResult;
-import android.security.KeystoreArguments;
-
-/**
- * This must be kept manually in sync with system/security/keystore until AIDL
- * can generate both Java and C++ bindings.
- *
- * @hide
- */
-interface IKeystoreService {
- int getState(int userId);
- byte[] get(String name, int uid);
- int insert(String name, in byte[] item, int uid, int flags);
- int del(String name, int uid);
- int exist(String name, int uid);
- String[] list(String namePrefix, int uid);
- int reset();
- int onUserPasswordChanged(int userId, String newPassword);
- int lock(int userId);
- int unlock(int userId, String userPassword);
- int isEmpty(int userId);
- int generate(String name, int uid, int keyType, int keySize, int flags,
- in KeystoreArguments args);
- int import_key(String name, in byte[] data, int uid, int flags);
- byte[] sign(String name, in byte[] data);
- int verify(String name, in byte[] data, in byte[] signature);
- byte[] get_pubkey(String name);
- String grant(String name, int granteeUid);
- int ungrant(String name, int granteeUid);
- long getmtime(String name, int uid);
- int is_hardware_backed(String string);
- int clear_uid(long uid);
-
- // Keymaster 0.4 methods
- int addRngEntropy(in byte[] data, int flags);
- int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid,
- int flags, out KeyCharacteristics characteristics);
- int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appId,
- int uid, out KeyCharacteristics characteristics);
- int importKey(String alias, in KeymasterArguments arguments, int format,
- in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics);
- ExportResult exportKey(String alias, int format, in KeymasterBlob clientId,
- in KeymasterBlob appId, int uid);
- OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
- in KeymasterArguments params, in byte[] entropy, int uid);
- OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
- OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature,
- in byte[] entropy);
- int abort(IBinder handle);
- boolean isOperationAuthorized(IBinder token);
- int addAuthToken(in byte[] authToken);
- int onUserAdded(int userId, int parentId);
- int onUserRemoved(int userId);
- int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain);
- int attestDeviceIds(in KeymasterArguments params, out KeymasterCertificateChain chain);
- int onDeviceOffBody();
- int importWrappedKey(in String wrappedKeyAlias, in byte[] wrappedKey,
- in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments,
- in long rootSid, in long fingerprintSid,
- out KeyCharacteristics characteristics);
- int presentConfirmationPrompt(IBinder listener, String promptText, in byte[] extraData,
- in String locale, in int uiOptionsAsFlags);
- int cancelConfirmationPrompt(IBinder listener);
-}
diff --git a/core/java/android/security/KeystoreArguments.aidl b/core/java/android/security/KeystoreArguments.aidl
deleted file mode 100644
index dc8ed50..0000000
--- a/core/java/android/security/KeystoreArguments.aidl
+++ /dev/null
@@ -1,20 +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.security;
-
-/* @hide */
-parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h";
diff --git a/core/java/android/security/keymaster/ExportResult.aidl b/core/java/android/security/keymaster/ExportResult.aidl
deleted file mode 100644
index 1748653..0000000
--- a/core/java/android/security/keymaster/ExportResult.aidl
+++ /dev/null
@@ -1,20 +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.security.keymaster;
-
-/* @hide */
-parcelable ExportResult cpp_header "keystore/ExportResult.h";
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.aidl b/core/java/android/security/keymaster/KeyCharacteristics.aidl
deleted file mode 100644
index 32e75ad..0000000
--- a/core/java/android/security/keymaster/KeyCharacteristics.aidl
+++ /dev/null
@@ -1,20 +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.security.keymaster;
-
-/* @hide */
-parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h";
diff --git a/core/java/android/security/keymaster/KeymasterArguments.aidl b/core/java/android/security/keymaster/KeymasterArguments.aidl
deleted file mode 100644
index 44d9f09..0000000
--- a/core/java/android/security/keymaster/KeymasterArguments.aidl
+++ /dev/null
@@ -1,20 +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.security.keymaster;
-
-/* @hide */
-parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/core/java/android/security/keymaster/KeymasterBlob.aidl b/core/java/android/security/keymaster/KeymasterBlob.aidl
deleted file mode 100644
index 5c5db9e..0000000
--- a/core/java/android/security/keymaster/KeymasterBlob.aidl
+++ /dev/null
@@ -1,20 +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.security.keymaster;
-
-/* @hide */
-parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h";
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
deleted file mode 100644
index ddb5cae..0000000
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* @hide */
-parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h";
diff --git a/core/java/android/security/keymaster/OperationResult.aidl b/core/java/android/security/keymaster/OperationResult.aidl
deleted file mode 100644
index db689d4..0000000
--- a/core/java/android/security/keymaster/OperationResult.aidl
+++ /dev/null
@@ -1,20 +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.security.keymaster;
-
-/* @hide */
-parcelable OperationResult cpp_header "keystore/OperationResult.h";
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index 7383de7..f644887 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -32,12 +32,12 @@
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.util.Xml;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -80,7 +80,7 @@
private final String mSettingsActivity;
@Nullable
- private final Map<String, Long> mCompatibilityPackages;
+ private final Map<String, Pair<Long, String>> mCompatibilityPackages;
public AutofillServiceInfo(Context context, ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
@@ -118,7 +118,7 @@
}
String settingsActivity = null;
- Map<String, Long> compatibilityPackages = null;
+ Map<String, Pair<Long, String>> compatibilityPackages = null;
try {
final Resources resources = context.getPackageManager().getResourcesForApplication(
@@ -154,9 +154,10 @@
mCompatibilityPackages = compatibilityPackages;
}
- private Map<String, Long> parseCompatibilityPackages(XmlPullParser parser, Resources resources)
+ private Map<String, Pair<Long, String>> parseCompatibilityPackages(XmlPullParser parser,
+ Resources resources)
throws IOException, XmlPullParserException {
- Map<String, Long> compatibilityPackages = null;
+ Map<String, Pair<Long, String>> compatibilityPackages = null;
final int outerDepth = parser.getDepth();
int type;
@@ -200,11 +201,13 @@
} else {
maxVersionCode = Long.MAX_VALUE;
}
+ final String urlBarResourceId = cpAttributes.getString(
+ R.styleable.AutofillService_CompatibilityPackage_urlBarResourceId);
if (compatibilityPackages == null) {
compatibilityPackages = new ArrayMap<>();
}
- compatibilityPackages.put(name, maxVersionCode);
+ compatibilityPackages.put(name, new Pair<>(maxVersionCode, urlBarResourceId));
} finally {
XmlUtils.skipCurrentTag(parser);
if (cpAttributes != null) {
@@ -226,16 +229,28 @@
return mSettingsActivity;
}
- @Nullable
public boolean isCompatibilityModeRequested(String packageName, long versionCode) {
if (mCompatibilityPackages == null) {
return false;
}
- final Long maxVersionCode = mCompatibilityPackages.get(packageName);
- if (maxVersionCode == null) {
+ final Pair<Long, String> pair = mCompatibilityPackages.get(packageName);
+ if (pair == null) {
return false;
}
- return versionCode <= maxVersionCode;
+ return versionCode <= pair.first;
+ }
+
+ /**
+ * Gets the resource id of the URL bar for a package. Used in compat mode
+ */
+ // TODO: return a list of strings instead
+ @Nullable
+ public String getUrlBarResourceId(String packageName) {
+ if (mCompatibilityPackages == null) {
+ return null;
+ }
+ final Pair<Long, String> pair = mCompatibilityPackages.get(packageName);
+ return pair == null ? null : pair.second;
}
@Override
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index cda2f4a..535c00b 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -177,30 +177,6 @@
return foundNodes;
}
- /**
- * Finds the {@link ViewNode} that has the requested {@code id}, if any.
- *
- * @hide
- */
- @Nullable public ViewNode findViewNodeByAutofillId(@NonNull AutofillId id) {
- final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
- final int numWindowNodes = mStructure.getWindowNodeCount();
- for (int i = 0; i < numWindowNodes; i++) {
- nodesToProcess.add(mStructure.getWindowNodeAt(i).getRootViewNode());
- }
- while (!nodesToProcess.isEmpty()) {
- final ViewNode node = nodesToProcess.removeFirst();
- if (id.equals(node.getAutofillId())) {
- return node;
- }
- for (int i = 0; i < node.getChildCount(); i++) {
- nodesToProcess.addLast(node.getChildAt(i));
- }
- }
-
- return null;
- }
-
public static final Parcelable.Creator<FillContext> CREATOR =
new Parcelable.Creator<FillContext>() {
@Override
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 4805318..3350f3e 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -34,7 +34,7 @@
*/
public static boolean logStart(int label) {
if (label >= 0 && label < 16) {
- StatsLog.write(APP_HOOK, label, APP_HOOK__STATE__START);
+ StatsLog.write(APP_BREADCRUMB_REPORTED, label, APP_BREADCRUMB_REPORTED__STATE__START);
return true;
}
return false;
@@ -48,7 +48,7 @@
*/
public static boolean logStop(int label) {
if (label >= 0 && label < 16) {
- StatsLog.write(APP_HOOK, label, APP_HOOK__STATE__STOP);
+ StatsLog.write(APP_BREADCRUMB_REPORTED, label, APP_BREADCRUMB_REPORTED__STATE__STOP);
return true;
}
return false;
@@ -62,7 +62,8 @@
*/
public static boolean logEvent(int label) {
if (label >= 0 && label < 16) {
- StatsLog.write(APP_HOOK, label, APP_HOOK__STATE__UNSPECIFIED);
+ StatsLog.write(APP_BREADCRUMB_REPORTED, label,
+ APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
return true;
}
return false;
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 370c97e..e50d40e 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -331,6 +331,7 @@
private static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
private static final int FLAG_DUMP_RESET = 1 << 1;
+ private static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
@IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
FLAG_DUMP_FRAMESTATS,
@@ -636,7 +637,10 @@
*/
void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
pw.flush();
- int flags = 0;
+ // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
+ // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
+ // dump the summary information
+ int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "framestats":
@@ -645,6 +649,9 @@
case "reset":
flags |= FLAG_DUMP_RESET;
break;
+ case "-a": // magic option passed when dumping a bugreport.
+ flags = FLAG_DUMP_ALL;
+ break;
}
}
nDumpProfileInfo(mNativeProxy, fd, flags);
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 990fbdb..29f8442 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -18,6 +18,7 @@
import android.annotation.AnimRes;
import android.annotation.InterpolatorRes;
+import android.annotation.TestApi;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
@@ -58,14 +59,43 @@
}
};
- /** @hide */
+ /**
+ * Locks AnimationUtils{@link #currentAnimationTimeMillis()} to a fixed value for the current
+ * thread. This is used by {@link android.view.Choreographer} to ensure that all accesses
+ * during a vsync update are synchronized to the timestamp of the vsync.
+ *
+ * It is also exposed to tests to allow for rapid, flake-free headless testing.
+ *
+ * Must be followed by a call to {@link #unlockAnimationClock()} to allow time to
+ * progress. Failing to do this will result in stuck animations, scrolls, and flings.
+ *
+ * Note that time is not allowed to "rewind" and must perpetually flow forward. So the
+ * lock may fail if the time is in the past from a previously returned value, however
+ * time will be frozen for the duration of the lock. The clock is a thread-local, so
+ * ensure that {@link #lockAnimationClock(long)}, {@link #unlockAnimationClock()}, and
+ * {@link #currentAnimationTimeMillis()} are all called on the same thread.
+ *
+ * This is also not reference counted in any way. Any call to {@link #unlockAnimationClock()}
+ * will unlock the clock for everyone on the same thread. It is therefore recommended
+ * for tests to use their own thread to ensure that there is no collision with any existing
+ * {@link android.view.Choreographer} instance.
+ *
+ * @hide
+ * */
+ @TestApi
public static void lockAnimationClock(long vsyncMillis) {
AnimationState state = sAnimationState.get();
state.animationClockLocked = true;
state.currentVsyncTimeMillis = vsyncMillis;
}
- /** @hide */
+ /**
+ * Frees the time lock set in place by {@link #lockAnimationClock(long)}. Must be called
+ * to allow the animation clock to self-update.
+ *
+ * @hide
+ */
+ @TestApi
public static void unlockAnimationClock() {
sAnimationState.get().animationClockLocked = false;
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 8b64bad..41d05a5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1407,7 +1407,8 @@
mSessionId = mService.startSession(client.autofillClientGetActivityToken(),
mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
- mCallback != null, flags, client.autofillClientGetComponentName());
+ mCallback != null, flags, client.autofillClientGetComponentName(),
+ isCompatibilityModeEnabledLocked());
if (mSessionId != NO_SESSION) {
mState = STATE_ACTIVE;
}
@@ -1474,7 +1475,7 @@
client.autofillClientGetActivityToken(),
mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
mCallback != null, flags, client.autofillClientGetComponentName(),
- mSessionId, action);
+ mSessionId, action, isCompatibilityModeEnabledLocked());
if (newId != mSessionId) {
if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId);
mSessionId = newId;
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 0018547..56f79ab 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -38,7 +38,7 @@
void removeClient(in IAutoFillManagerClient client, int userId);
int startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
- in ComponentName componentName);
+ in ComponentName componentName, boolean compatMode);
FillEventHistory getFillEventHistory();
boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
void updateSession(int sessionId, in AutofillId id, in Rect bounds,
@@ -46,7 +46,7 @@
int updateOrRestartSession(IBinder activityToken, in IBinder appCallback,
in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
boolean hasCallback, int flags, in ComponentName componentName, int sessionId,
- int action);
+ int action, boolean compatMode);
void finishSession(int sessionId, int userId);
void cancelSession(int sessionId, int userId);
void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index eb58b09..6a56f45 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -187,7 +187,7 @@
public final AtomicFile mCheckinFile;
public final AtomicFile mDailyFile;
- static final int MSG_UPDATE_WAKELOCKS = 1;
+ static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
static final int MSG_REPORT_POWER_CHANGE = 2;
static final int MSG_REPORT_CHARGING = 3;
static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
@@ -273,10 +273,7 @@
public void handleMessage(Message msg) {
BatteryCallback cb = mCallback;
switch (msg.what) {
- case MSG_UPDATE_WAKELOCKS:
- synchronized (BatteryStatsImpl.this) {
- updateCpuTimeLocked();
- }
+ case MSG_REPORT_CPU_UPDATE_NEEDED:
if (cb != null) {
cb.batteryNeedsCpuUpdate();
}
@@ -302,6 +299,10 @@
}
}
+ public void postBatteryNeedsCpuUpdateMsg() {
+ mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
+ }
+
/**
* Update per-freq cpu times for all the uids in {@link #mPendingUids}.
*/
@@ -487,6 +488,10 @@
Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
Future<?> scheduleCpuSyncDueToSettingChange();
+ Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
+ boolean onBatteryScreenOff);
+ Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
+ void cancelCpuSyncDueToWakelockChange();
}
public Handler mHandler;
@@ -1453,12 +1458,10 @@
long mCount;
long mLoadedCount;
long mUnpluggedCount;
- long mPluggedCount;
LongSamplingCounter(TimeBase timeBase, Parcel in) {
mTimeBase = timeBase;
- mPluggedCount = in.readLong();
- mCount = mPluggedCount;
+ mCount = in.readLong();
mLoadedCount = in.readLong();
mUnpluggedCount = in.readLong();
timeBase.add(this);
@@ -1477,16 +1480,15 @@
@Override
public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
- mUnpluggedCount = mPluggedCount;
+ mUnpluggedCount = mCount;
}
@Override
public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
- mPluggedCount = mCount;
}
public long getCountLocked(int which) {
- long val = mTimeBase.isRunning() ? mCount : mPluggedCount;
+ long val = mCount;
if (which == STATS_SINCE_UNPLUGGED) {
val -= mUnpluggedCount;
} else if (which != STATS_SINCE_CHARGED) {
@@ -1499,12 +1501,15 @@
public void logState(Printer pw, String prefix) {
pw.println(prefix + "mCount=" + mCount
+ " mLoadedCount=" + mLoadedCount
- + " mUnpluggedCount=" + mUnpluggedCount
- + " mPluggedCount=" + mPluggedCount);
+ + " mUnpluggedCount=" + mUnpluggedCount);
}
void addCountLocked(long count) {
- if (mTimeBase.isRunning()) {
+ addCountLocked(count, mTimeBase.isRunning());
+ }
+
+ void addCountLocked(long count, boolean isRunning) {
+ if (isRunning) {
mCount += count;
}
}
@@ -1514,7 +1519,7 @@
*/
void reset(boolean detachIfReset) {
mCount = 0;
- mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
+ mLoadedCount = mUnpluggedCount = 0;
if (detachIfReset) {
detach();
}
@@ -1531,7 +1536,7 @@
void readSummaryFromParcelLocked(Parcel in) {
mLoadedCount = in.readLong();
mCount = mLoadedCount;
- mUnpluggedCount = mPluggedCount = mLoadedCount;
+ mUnpluggedCount = mLoadedCount;
}
}
@@ -3852,9 +3857,6 @@
+ Display.stateToString(screenState)
+ " and battery is " + (unplugged ? "on" : "off"));
}
- updateCpuTimeLocked();
- mExternalSync.scheduleCopyFromAllUidsCpuTimes(mOnBatteryTimeBase.isRunning(),
- mOnBatteryScreenOffTimeBase.isRunning());
mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
if (updateOnBatteryTimeBase) {
@@ -4143,15 +4145,11 @@
}
private void requestWakelockCpuUpdate() {
- if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
- Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
- mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
- }
+ mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
}
private void requestImmediateCpuUpdate() {
- mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
- mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
+ mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
}
public void setRecordAllHistoryLocked(boolean enabled) {
@@ -4554,7 +4552,7 @@
}
public boolean startAddingCpuLocked() {
- mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ mExternalSync.cancelCpuSyncDueToWakelockChange();
return mOnBatteryInternal;
}
@@ -4807,6 +4805,8 @@
+ Display.stateToString(state));
addHistoryRecordLocked(elapsedRealtime, uptime);
}
+ mExternalSync.scheduleCpuSyncDueToScreenStateChange(
+ mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
if (isScreenOn(state)) {
updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
@@ -9196,8 +9196,14 @@
}
public void addCpuTimeLocked(int utime, int stime) {
- mUserTime += utime;
- mSystemTime += stime;
+ addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
+ }
+
+ public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
+ if (isRunning) {
+ mUserTime += utime;
+ mSystemTime += stime;
+ }
}
public void addForegroundTimeLocked(long ttime) {
@@ -11761,13 +11767,24 @@
}
}
+ public boolean isOnBatteryLocked() {
+ return mOnBatteryTimeBase.isRunning();
+ }
+
+ public boolean isOnBatteryScreenOffLocked() {
+ return mOnBatteryScreenOffTimeBase.isRunning();
+ }
+
/**
* Read and distribute CPU usage across apps. If their are partial wakelocks being held
* and we are on battery with screen off, we give more of the cpu time to those apps holding
* wakelocks. If the screen is on, we just assign the actual cpu time an app used.
+ * It's possible this will be invoked after the internal battery/screen states are updated, so
+ * passing the appropriate battery/screen states to try attribute the cpu times to correct
+ * buckets.
*/
@GuardedBy("this")
- public void updateCpuTimeLocked() {
+ public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
if (mPowerProfile == null) {
return;
}
@@ -11784,7 +11801,7 @@
// usually holding the wakelock on behalf of an app.
// And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
ArrayList<StopwatchTimer> partialTimersToConsider = null;
- if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ if (onBatteryScreenOff) {
partialTimersToConsider = new ArrayList<>();
for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
final StopwatchTimer timer = mPartialTimers.get(i);
@@ -11802,7 +11819,7 @@
// When the battery is not on, we don't attribute the cpu times to any timers but we still
// need to take the snapshots.
- if (!mOnBatteryInternal) {
+ if (!onBattery) {
mKernelUidCpuTimeReader.readDelta(null);
mKernelUidCpuFreqTimeReader.readDelta(null);
if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
@@ -11818,16 +11835,16 @@
mUserInfoProvider.refreshUserIds();
final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
? null : new SparseLongArray();
- readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids);
+ readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
// updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
// freqs, so no need to approximate these values.
if (updatedUids != null) {
- updateClusterSpeedTimes(updatedUids);
+ updateClusterSpeedTimes(updatedUids, onBattery);
}
- readKernelUidCpuFreqTimesLocked(partialTimersToConsider);
+ readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
- readKernelUidCpuActiveTimesLocked();
- readKernelUidCpuClusterTimesLocked();
+ readKernelUidCpuActiveTimesLocked(onBattery);
+ readKernelUidCpuClusterTimesLocked(onBattery);
}
}
@@ -11867,7 +11884,7 @@
* @param updatedUids The uids for which times spent at different frequencies are calculated.
*/
@VisibleForTesting
- public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids) {
+ public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
long totalCpuClustersTimeMs = 0;
// Read the time spent for each cluster at various cpu frequencies.
final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
@@ -11909,7 +11926,7 @@
}
cpuSpeeds[speed].addCountLocked(appCpuTimeUs
* clusterSpeedTimesMs[cluster][speed]
- / totalCpuClustersTimeMs);
+ / totalCpuClustersTimeMs, onBattery);
}
}
}
@@ -11926,7 +11943,7 @@
*/
@VisibleForTesting
public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
- @Nullable SparseLongArray updatedUids) {
+ @Nullable SparseLongArray updatedUids, boolean onBattery) {
mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
final long startTimeMs = mClocks.uptimeMillis();
@@ -11977,8 +11994,8 @@
Slog.d(TAG, sb.toString());
}
- u.mUserCpuTime.addCountLocked(userTimeUs);
- u.mSystemCpuTime.addCountLocked(systemTimeUs);
+ u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
+ u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
if (updatedUids != null) {
updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
}
@@ -12010,15 +12027,15 @@
Slog.d(TAG, sb.toString());
}
- timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
- timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
+ timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
+ timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
if (updatedUids != null) {
final int uid = timer.mUid.getUid();
updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
}
final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
- proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
+ proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
mTempTotalCpuUserTimeUs -= userTimeUs;
mTempTotalCpuSystemTimeUs -= systemTimeUs;
@@ -12033,7 +12050,8 @@
* @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
*/
@VisibleForTesting
- public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers) {
+ public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
+ boolean onBattery, boolean onBatteryScreenOff) {
final boolean perClusterTimesAvailable =
mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
@@ -12056,13 +12074,13 @@
if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
}
- u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
+ u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
if (u.mScreenOffCpuFreqTimeMs == null ||
u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
mOnBatteryScreenOffTimeBase);
}
- u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
+ u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
if (perClusterTimesAvailable) {
if (u.mCpuClusterSpeedTimesUs == null ||
@@ -12098,7 +12116,7 @@
} else {
appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
}
- cpuTimesUs[speed].addCountLocked(appAllocationUs);
+ cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
freqIndex++;
}
}
@@ -12132,7 +12150,7 @@
}
final long allocationUs =
mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
- cpuTimeUs[speed].addCountLocked(allocationUs);
+ cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
}
}
@@ -12145,7 +12163,7 @@
* counters.
*/
@VisibleForTesting
- public void readKernelUidCpuActiveTimesLocked() {
+ public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
final long startTimeMs = mClocks.uptimeMillis();
mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesUs) -> {
uid = mapUid(uid);
@@ -12160,7 +12178,7 @@
return;
}
final Uid u = getUidStatsLocked(uid);
- u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs);
+ u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs, onBattery);
});
final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
@@ -12174,7 +12192,7 @@
* counters.
*/
@VisibleForTesting
- public void readKernelUidCpuClusterTimesLocked() {
+ public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
final long startTimeMs = mClocks.uptimeMillis();
mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesUs) -> {
uid = mapUid(uid);
@@ -12189,7 +12207,7 @@
return;
}
final Uid u = getUidStatsLocked(uid);
- u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs);
+ u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs, onBattery);
});
final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
@@ -12399,9 +12417,7 @@
reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
status, plugType, level, temp);
- final boolean onBattery =
- plugType == BATTERY_PLUGGED_NONE &&
- status != BatteryManager.BATTERY_STATUS_UNKNOWN;
+ final boolean onBattery = isOnBattery(plugType, status);
final long uptime = mClocks.uptimeMillis();
final long elapsedRealtime = mClocks.elapsedRealtime();
if (!mHaveBatteryLevel) {
@@ -12591,6 +12607,10 @@
mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
}
+ public static boolean isOnBattery(int plugType, int status) {
+ return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
+ }
+
// Inform StatsLog of setBatteryState changes.
// If this is the first reporting, pass in recentPast == null.
private void reportChangesToStatsLog(HistoryItem recentPast,
diff --git a/core/res/res/drawable/ic_settings_24dp.xml b/core/res/res/drawable/ic_settings_24dp.xml
index fc75f04..c70b122 100644
--- a/core/res/res/drawable/ic_settings_24dp.xml
+++ b/core/res/res/drawable/ic_settings_24dp.xml
@@ -16,9 +16,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
- android:pathData="M38.86 25.95c.08,-.64.14,-1.29.14,-1.95s-.06,-1.31,-.14,-1.95l4.23,-3.31c.38,-.3.49,-.84.24,-1.28l-4,-6.93c-.25,-.43,-.77,-.61,-1.22,-.43l-4.98 2.01c-1.03,-.79,-2.16,-1.46,-3.38,-1.97L29 4.84c-.09,-.47,-.5,-.84,-1,-.84h-8c-.5 0,-.91.37,-.99.84l-.75 5.3c-1.22.51,-2.35 1.17,-3.38 1.97L9.9 10.1c-.45,-.17,-.97 0,-1.22.43l-4 6.93c-.25.43,-.14.97.24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31.14 1.95l-4.22 3.31c-.38.3,-.49.84,-.24 1.28l4 6.93c.25.43.77.61 1.22.43l4.98,-2.01c1.03.79 2.16 1.46 3.38 1.97l.75 5.3c.08.47.49.84.99.84h8c.5 0 .91,-.37.99,-.84l.75,-5.3c1.22,-.51 2.35,-1.17 3.38,-1.97l4.98 2.01c.45.17.97 0 1.22,-.43l4,-6.93c.25,-.43.14,-.97,-.24,-1.28l-4.22,-3.31zM24 31c-3.87 0,-7,-3.13,-7,-7s3.13,-7 7,-7 7 3.13 7 7,-3.13 7,-7 7z"/>
+ android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
+ android:fillColor="#FF000000" />
</vector>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 005d07d..d26567e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7918,6 +7918,10 @@
android.content.pm.PackageInfo#getLongVersionCode()} for the target package.
-->
<attr name="maxLongVersionCode" format="string" />
+ <!-- The resource id of view that contains the URL bar of the HTML page being loaded.
+ Typically used when compatibility mode is used in a browser.
+ -->
+ <attr name="urlBarResourceId" format="string" />
</declare-styleable>
<!-- =============================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cf7925b..0218750 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2913,8 +2913,8 @@
<item name="config_pictureInPictureAspectRatioLimitForMinSize" format="float" type="dimen">1.777778</item>
<!-- The default gravity for the picture-in-picture window.
- Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
- <integer name="config_defaultPictureInPictureGravity">0x55</integer>
+ Currently, this maps to Gravity.TOP | Gravity.RIGHT -->
+ <integer name="config_defaultPictureInPictureGravity">0x35</integer>
<!-- The minimum aspect ratio (width/height) that is supported for picture-in-picture. Any
ratio smaller than this is considered too tall and thin to be usable. Currently, this
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 93f22f25..82fefef 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2869,6 +2869,7 @@
<public name="outlineSpotShadowColor" />
<public name="outlineAmbientShadowColor" />
<public name="maxLongVersionCode" />
+ <public name="urlBarResourceId" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index 32053e3..cb049b7 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -114,7 +114,7 @@
when(mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs);
// RUN
- mBatteryStatsImpl.updateCpuTimeLocked();
+ mBatteryStatsImpl.updateCpuTimeLocked(false, false);
// VERIFY
assertArrayEquals("Unexpected cpu freqs", freqs, mBatteryStatsImpl.getCpuFreqs());
@@ -134,7 +134,7 @@
mBatteryStatsImpl.setOnBatteryInternal(true);
// RUN
- mBatteryStatsImpl.updateCpuTimeLocked();
+ mBatteryStatsImpl.updateCpuTimeLocked(true, false);
// VERIFY
verify(mUserInfoProvider).refreshUserIds();
@@ -213,7 +213,7 @@
}
// RUN
- mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids);
+ mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true);
// VERIFY
int totalClustersTimeMs = 0;
@@ -261,7 +261,7 @@
// RUN
final SparseLongArray updatedUids = new SparseLongArray();
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -294,7 +294,7 @@
}).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -333,7 +333,7 @@
}).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -368,7 +368,7 @@
}).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -423,7 +423,7 @@
}).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -470,7 +470,7 @@
// RUN
final SparseLongArray updatedUids = new SparseLongArray();
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids, true);
// VERIFY
long totalUserTimeUs = 0;
@@ -549,7 +549,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -582,7 +582,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -633,7 +633,7 @@
when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -676,7 +676,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -743,7 +743,7 @@
when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false);
// VERIFY
final long[][] expectedWakeLockUidTimesUs = new long[clusterFreqs.length][];
@@ -832,7 +832,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -865,7 +865,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -909,7 +909,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -949,7 +949,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1006,7 +1006,7 @@
any(KernelUidCpuFreqTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+ mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1047,7 +1047,7 @@
any(KernelUidCpuActiveTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1073,7 +1073,7 @@
any(KernelUidCpuActiveTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1112,7 +1112,7 @@
any(KernelUidCpuClusterTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1142,7 +1142,7 @@
any(KernelUidCpuClusterTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 82ac9da..01ddc15 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -161,9 +161,7 @@
actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
elapsedTimeUs, STATS_SINCE_CHARGED);
- expectedRunTimeMs = stateRuntimeMap.get(
- ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE)
- + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
@@ -173,7 +171,8 @@
actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND,
elapsedTimeUs, STATS_SINCE_CHARGED);
- expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
+ + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND,
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index 7b239f0..cb05253 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -171,6 +171,20 @@
return null;
}
+ @Override
+ public Future<?> scheduleCpuSyncDueToScreenStateChange(
+ boolean onBattery, boolean onBatteryScreenOff) {
+ return null;
+ }
+
+ @Override
+ public Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis) {
+ return null;
+ }
+
+ @Override
+ public void cancelCpuSyncDueToWakelockChange() {
+ }
}
}
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
index 994131a..9b9e811 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
@@ -29,13 +29,10 @@
LOCAL_SRC_FILES:= \
native.cpp
-# All of the shard libraries we link against.
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_LDLIBS := -llog
LOCAL_CFLAGS += -Wall -Wextra -Werror
-# Also need the JNI headers.
-LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
index 99cf587..fe32454 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
@@ -15,12 +15,15 @@
*/
#define LOG_TAG "pmtest32 native.cpp"
-#include <utils/Log.h>
+#include <android/log.h>
#include <stdio.h>
#include "jni.h"
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
static jint
add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
int result = a + b;
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
index 6c2679b..600a5d1 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
@@ -30,14 +30,10 @@
LOCAL_SRC_FILES:= \
native.cpp
-# All of the shared libraries we link against.
-LOCAL_SHARED_LIBRARIES := \
- libutils liblog
+LOCAL_LDLIBS := -llog
LOCAL_CFLAGS += -Wall -Wextra -Werror
-# Also need the JNI headers.
-LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
index 0b6d750..ad9e746 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
@@ -15,12 +15,15 @@
*/
#define LOG_TAG "pmtest64 native.cpp"
-#include <utils/Log.h>
+#include <android/log.h>
#include <stdio.h>
#include "jni.h"
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
static jint
add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
int result = a + b;
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
index d668f29..8e9ac6b 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
@@ -29,14 +29,10 @@
LOCAL_SRC_FILES:= \
native.cpp
-# All of the shard libraries we link against.
LOCAL_LDLIBS = -llog
-LOCAL_SHARED_LIBRARIES := liblog
LOCAL_CFLAGS += -Wall -Wextra -Werror
-# Also need the JNI headers.
-LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
index 3947e21..5c5088f 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
@@ -15,12 +15,15 @@
*/
#define LOG_TAG "pmtestdual native.cpp"
-#include <utils/Log.h>
+#include <android/log.h>
#include <stdio.h>
#include "jni.h"
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
static jint
add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
int result = a + b;
diff --git a/media/OWNERS b/media/OWNERS
new file mode 100644
index 0000000..8f405e9
--- /dev/null
+++ b/media/OWNERS
@@ -0,0 +1,4 @@
+elaurent@google.com
+etalvala@google.com
+lajos@google.com
+marcone@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 1a54d6a..b98f27e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -76,6 +76,8 @@
protected Uri mForeverId;
private int mBucketIndex = -1;
+ @VisibleForTesting
+ protected NotificationManager mNotificationManager;
private AlarmManager mAlarmManager;
private int mUserId;
private boolean mAttached;
@@ -98,7 +100,7 @@
}
public Dialog createDialog() {
- NotificationManager noMan = (NotificationManager) mContext.
+ mNotificationManager = (NotificationManager) mContext.
getSystemService(Context.NOTIFICATION_SERVICE);
mForeverId = Condition.newId(mContext).appendPath("forever").build();
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
@@ -131,7 +133,8 @@
Slog.d(TAG, "Invalid manual condition: " + tag.condition);
}
// always triggers priority-only dnd with chosen condition
- noMan.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ mNotificationManager.setZenMode(
+ Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
getRealConditionId(tag.condition), TAG);
}
});
@@ -465,7 +468,16 @@
mZenAlarmWarning.setVisibility(warningText == null ? View.GONE : View.VISIBLE);
}
- private String computeAlarmWarningText(Condition condition) {
+ @VisibleForTesting
+ protected String computeAlarmWarningText(Condition condition) {
+ boolean allowAlarms = (mNotificationManager.getNotificationPolicy().priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) != 0;
+
+ // don't show alarm warning if alarms are allowed to bypass dnd
+ if (allowAlarms) {
+ return null;
+ }
+
final long now = System.currentTimeMillis();
final long nextAlarm = getNextAlarm();
if (nextAlarm < now) {
@@ -483,14 +495,19 @@
if (warningRes == 0) {
return null;
}
+
+ return mContext.getResources().getString(warningRes, getTime(nextAlarm, now));
+ }
+
+ @VisibleForTesting
+ protected String getTime(long nextAlarm, long now) {
final boolean soon = (nextAlarm - now) < 24 * 60 * 60 * 1000;
final boolean is24 = DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser());
final String skeleton = soon ? (is24 ? "Hm" : "hma") : (is24 ? "EEEHm" : "EEEhma");
final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
final CharSequence formattedTime = DateFormat.format(pattern, nextAlarm);
final int templateRes = soon ? R.string.alarm_template : R.string.alarm_template_far;
- final String template = mContext.getResources().getString(templateRes, formattedTime);
- return mContext.getResources().getString(warningRes, template);
+ return mContext.getResources().getString(templateRes, formattedTime);
}
// used as the view tag on condition rows
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 9b5da4a..ccd2f53 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -17,15 +17,22 @@
package com.android.settingslib.notification;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.Fragment;
+import android.app.NotificationManager;
import android.content.Context;
+import android.content.res.Resources;
import android.net.Uri;
import android.service.notification.Condition;
import android.view.LayoutInflater;
@@ -46,7 +53,11 @@
@Mock
private Context mContext;
@Mock
+ private Resources mResources;
+ @Mock
private Fragment mFragment;
+ @Mock
+ private NotificationManager mNotificationManager;
private Context mShadowContext;
private LayoutInflater mLayoutInflater;
@@ -58,6 +69,7 @@
MockitoAnnotations.initMocks(this);
mShadowContext = RuntimeEnvironment.application;
when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getResources()).thenReturn(mResources);
when(mFragment.getContext()).thenReturn(mShadowContext);
mLayoutInflater = LayoutInflater.from(mShadowContext);
@@ -67,6 +79,10 @@
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
.thenReturn("testSummary");
+ NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
+ NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
+ doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
+ mController.mNotificationManager = mNotificationManager;
mController.getContentView();
// these methods use static calls to ZenModeConfig which would normally fail in robotests,
@@ -141,4 +157,38 @@
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
+
+ @Test
+ public void testNoAlarmWarning() {
+ // setup alarm
+ long now = System.currentTimeMillis();
+ doReturn(now + 100000).when(mController).getNextAlarm();
+ doReturn("").when(mController).getTime(anyLong(), anyLong());
+
+ // allow alarms
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(
+ new NotificationManager.Policy(
+ NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0));
+
+ // alarm warning should be null
+ assertNull(mController.computeAlarmWarningText(null));
+ }
+
+ @Test
+ public void testAlarmWarning() {
+ // setup alarm
+ long now = System.currentTimeMillis();
+ doReturn(now + 1000000).when(mController).getNextAlarm();
+ doReturn("").when(mController).getTime(anyLong(), anyLong());
+
+ // don't allow alarms to bypass dnd
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(
+ new NotificationManager.Policy(0, 0, 0, 0));
+
+ // return a string if mResources is asked to retrieve a string
+ when(mResources.getString(anyInt(), anyString())).thenReturn("");
+
+ // alarm warning should NOT be null
+ assertNotNull(mController.computeAlarmWarningText(null));
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index af6dd77..7c97ca61 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -2,19 +2,23 @@
dsandler@google.com
+adamcohen@google.com
asc@google.com
ashaikh@google.com
beverlyt@google.com
cinek@google.com
cwren@google.com
+dupin@google.com
evanlaird@google.com
jmonk@google.com
jaggies@google.com
jjaggi@google.com
juliacr@google.com
-dupin@google.com
madym@google.com
+ngmatthew@google.com
roosa@google.com
shahrk@google.com
+sunnygoyal@google.com
+twickham@google.com
winsonc@google.com
diff --git a/packages/SystemUI/res/drawable/ic_lock_lockdown.xml b/packages/SystemUI/res/drawable/ic_lock_lockdown.xml
new file mode 100644
index 0000000..b517fc8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lock_lockdown.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:fillColor="#757575"
+ android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.8 -2.2,-5.0 -5.0,-5.0C9.2,1.0 7.0,3.2 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM12.0,17.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0c1.1,0.0 2.0,0.9 2.0,2.0S13.1,17.0 12.0,17.0zM15.1,8.0L8.9,8.0L8.9,6.0c0.0,-1.7 1.4,-3.1 3.1,-3.1c1.7,0.0 3.1,1.4 3.1,3.1L15.1,8.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 97472a4..cf88ade 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -71,23 +71,19 @@
android:singleLine="true" />
</LinearLayout>
- <FrameLayout
+ <View
+ android:id="@+id/qs_drag_handle_view"
android:layout_width="24dp"
- android:layout_height="match_parent" >
- <View
- android:id="@+id/qs_drag_handle_view"
- android:layout_width="match_parent"
- android:layout_height="4dp"
- android:layout_marginTop="28dp"
- android:background="@drawable/qs_footer_drag_handle" />
- </FrameLayout>
+ android:layout_height="4dp"
+ android:layout_gravity="center"
+ android:background="@drawable/qs_footer_drag_handle" />
- <LinearLayout
+ <com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/qs_footer_actions_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
- android:gravity="end" >
+ android:gravity="center_vertical|end" >
<com.android.systemui.statusbar.phone.MultiUserSwitch
android:id="@+id/multi_user_switch"
android:layout_width="48dp"
@@ -113,7 +109,7 @@
android:clipToPadding="false"
android:contentDescription="@string/accessibility_quick_settings_edit"
android:focusable="true"
- android:padding="16dp"
+ android:padding="15dp"
android:src="@drawable/ic_mode_edit"
android:tint="?android:attr/colorForeground"/>
@@ -131,6 +127,7 @@
android:layout_height="match_parent"
android:background="@drawable/ripple_drawable"
android:contentDescription="@string/accessibility_quick_settings_settings"
+ android:padding="15dp"
android:src="@drawable/ic_settings_16dp"
android:tint="?android:attr/colorForeground"/>
@@ -145,7 +142,7 @@
android:visibility="invisible"/>
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
- </LinearLayout>
+ </com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
</com.android.systemui.qs.QSFooterImpl>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a62f38b..d11ab42 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -230,7 +230,7 @@
<!-- The height of the quick settings footer that holds the user switcher, settings icon,
etc. -->
- <dimen name="qs_footer_height">48dp</dimen>
+ <dimen name="qs_footer_height">56dp</dimen>
<!-- The padding between the notifications and the quick settings container -->
<dimen name="qs_notification_padding">@dimen/notification_side_paddings</dimen>
@@ -337,7 +337,7 @@
<dimen name="qs_footer_padding_end">24dp</dimen>
<dimen name="qs_footer_icon_size">16dp</dimen>
<!-- Difference between drag handle margin in QQS and expanded QS -->
- <dimen name="qs_footer_drag_handle_offset">6dp</dimen>
+ <dimen name="qs_footer_drag_handle_offset">10dp</dimen>
<dimen name="qs_notif_collapsed_space">64dp</dimen>
@@ -513,7 +513,7 @@
<dimen name="multi_user_avatar_keyguard_size">22dp</dimen>
<!-- The width of user avatar when expanded -->
- <dimen name="multi_user_avatar_expanded_size">16dp</dimen>
+ <dimen name="multi_user_avatar_expanded_size">18dp</dimen>
<!-- The font size of the time when collapsed in QS -->
<dimen name="qs_time_collapsed_size">14sp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 1aea5e7..259bff2 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -688,7 +688,7 @@
}
private Action getLockdownAction() {
- return new SinglePressAction(R.drawable.ic_lock_lock,
+ return new SinglePressAction(com.android.systemui.R.drawable.ic_lock_lockdown,
R.string.global_action_lockdown) {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index fe3ffb9..b9919a3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -174,7 +174,8 @@
.addFloat(mDivider, "alpha", 0, 1)
.addFloat(mCarrierText, "alpha", 0, 1)
.addFloat(mActionsContainer, "alpha", 0, 1)
- .addFloat(mDragHandle, "translationY", 0, -mDragHandleExpandOffset)
+ .addFloat(mDragHandle, "translationY", mDragHandleExpandOffset, 0)
+ .addFloat(mDragHandle, "alpha", 1, 0)
.build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
index bb2f597..f4da0c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -89,6 +89,7 @@
private int mLightTrackColor;
private int mDarkTrackColor;
private float mDarkIntensity;
+ private View mHomeButtonView;
private final Handler mHandler = new Handler();
private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
@@ -114,11 +115,10 @@
if (!mQuickScrubActive) {
pos = mDragPositive ? Math.min((int) mTranslation, pos) : Math.max((int) mTranslation, pos);
}
- final View homeView = mNavigationBarView.getHomeButton().getCurrentView();
if (mIsVertical) {
- homeView.setTranslationY(pos);
+ mHomeButtonView.setTranslationY(pos);
} else {
- homeView.setTranslationX(pos);
+ mHomeButtonView.setTranslationX(pos);
}
};
@@ -126,6 +126,7 @@
@Override
public void onAnimationEnd(Animator animation) {
mNavigationBarView.getHomeButton().setClickable(true);
+ mHomeButtonView = null;
mQuickScrubActive = false;
mTranslation = 0;
}
@@ -226,6 +227,7 @@
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
+ mHomeButtonView = homeButton.getCurrentView();
if (isQuickScrubEnabled()
&& mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) {
mTouchDownX = x;
@@ -305,9 +307,9 @@
mTranslation /= SWITCH_STICKINESS;
}
if (mIsVertical) {
- homeButton.getCurrentView().setTranslationY(mTranslation);
+ mHomeButtonView.setTranslationY(mTranslation);
} else {
- homeButton.getCurrentView().setTranslationX(mTranslation);
+ mHomeButtonView.setTranslationX(mTranslation);
}
}
}
@@ -315,7 +317,7 @@
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- endQuickScrub();
+ endQuickScrub(true /* animate */);
break;
}
return mDraggingActive || mQuickScrubActive;
@@ -357,6 +359,11 @@
@Override
public void setBarState(boolean isVertical, boolean isRTL) {
+ final boolean changed = (mIsVertical != isVertical) || (mIsRTL != isRTL);
+ if (changed) {
+ // End quickscrub if the state changes mid-transition
+ endQuickScrub(false /* animate */);
+ }
mIsVertical = isVertical;
mIsRTL = isRTL;
try {
@@ -392,7 +399,7 @@
}
}
- private void endQuickScrub() {
+ private void endQuickScrub(boolean animate) {
mHandler.removeCallbacks(mLongPressRunnable);
if (mDraggingActive || mQuickScrubActive) {
mButtonAnimator.setIntValues((int) mTranslation, 0);
@@ -406,6 +413,9 @@
} catch (RemoteException e) {
Log.e(TAG, "Failed to send end of quick scrub.", e);
}
+ if (!animate) {
+ mQuickScrubEndAnimator.end();
+ }
}
mDraggingActive = false;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index c36bb6d..5b5d18f 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -446,8 +446,10 @@
mMagnificationRegion.getBounds(viewport);
final MagnificationSpec spec = mCurrentMagnificationSpec;
final float oldScale = spec.scale;
- final float oldCenterX = (viewport.width() / 2.0f - spec.offsetX) / oldScale;
- final float oldCenterY = (viewport.height() / 2.0f - spec.offsetY) / oldScale;
+ final float oldCenterX
+ = (viewport.width() / 2.0f - spec.offsetX + viewport.left) / oldScale;
+ final float oldCenterY
+ = (viewport.height() / 2.0f - spec.offsetY + viewport.top) / oldScale;
final float normPivotX = (pivotX - spec.offsetX) / oldScale;
final float normPivotY = (pivotY - spec.offsetY) / oldScale;
final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index d5a722b..ebb5040 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -580,7 +580,7 @@
@Override
public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
- ComponentName componentName) {
+ ComponentName componentName, boolean compatMode) {
activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
@@ -599,7 +599,7 @@
synchronized (mLock) {
final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
return service.startSessionLocked(activityToken, getCallingUid(), appCallback,
- autofillId, bounds, value, hasCallback, flags, componentName);
+ autofillId, bounds, value, hasCallback, flags, componentName, compatMode);
}
}
@@ -770,7 +770,7 @@
public int updateOrRestartSession(IBinder activityToken, IBinder appCallback,
AutofillId autoFillId, Rect bounds, AutofillValue value, int userId,
boolean hasCallback, int flags, ComponentName componentName, int sessionId,
- int action) {
+ int action, boolean compatMode) {
boolean restart = false;
synchronized (mLock) {
final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
@@ -783,7 +783,7 @@
}
if (restart) {
return startSession(activityToken, appCallback, autoFillId, bounds, value, userId,
- hasCallback, flags, componentName);
+ hasCallback, flags, componentName, compatMode);
}
// Nothing changed...
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 2dcc6da..75ae2dc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -220,6 +220,17 @@
return mInfo.getServiceInfo().applicationInfo.uid;
}
+
+ @GuardedBy("mLock")
+ @Nullable
+ String getUrlBarResourceIdForCompatModeLocked(@NonNull String packageName) {
+ if (mInfo == null) {
+ Slog.w(TAG, "getUrlBarResourceIdForCompatModeLocked(): no mInfo");
+ return null;
+ }
+ return mInfo.getUrlBarResourceId(packageName);
+ }
+
@Nullable
String getServicePackageName() {
final ComponentName serviceComponent = getServiceComponentName();
@@ -345,7 +356,7 @@
int startSessionLocked(@NonNull IBinder activityToken, int uid,
@NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId,
@NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
- int flags, @NonNull ComponentName componentName) {
+ int flags, @NonNull ComponentName componentName, boolean compatMode) {
if (!isEnabledLocked()) {
return 0;
}
@@ -375,7 +386,7 @@
pruneAbandonedSessionsLocked();
final Session newSession = createSessionByTokenLocked(activityToken, uid, appCallbackToken,
- hasCallback, componentName, flags);
+ hasCallback, componentName, compatMode, flags);
if (newSession == null) {
return NO_SESSION;
}
@@ -481,7 +492,7 @@
@GuardedBy("mLock")
private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid,
@NonNull IBinder appCallbackToken, boolean hasCallback,
- @NonNull ComponentName componentName, int flags) {
+ @NonNull ComponentName componentName, boolean compatMode, int flags) {
// use random ids so that one app cannot know that another app creates sessions
int sessionId;
int tries = 0;
@@ -499,7 +510,8 @@
final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock,
sessionId, uid, activityToken, appCallbackToken, hasCallback, mUiLatencyHistory,
- mWtfHistory, mInfo.getServiceInfo().getComponentName(), componentName, flags);
+ mWtfHistory, mInfo.getServiceInfo().getComponentName(), componentName, compatMode,
+ flags);
mSessions.put(newSession.id, newSession);
return newSession;
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 02a62e1..5ef467d 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -18,11 +18,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
import android.metrics.LogMaker;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -31,11 +34,14 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;
public final class Helper {
+ private static final String TAG = "AutofillHelper";
+
/**
* Defines a logging flag that can be dynamically changed at runtime using
* {@code cmd autofill set log_level debug}.
@@ -121,4 +127,61 @@
pw.print(text.length()); pw.println("_chars");
}
}
+
+ /**
+ * Finds the {@link ViewNode} that has the requested {@code autofillId}, if any.
+ */
+ @Nullable
+ public static ViewNode findViewNodeByAutofillId(@NonNull AssistStructure structure,
+ @NonNull AutofillId autofillId) {
+ return findViewNode(structure, (node) -> {
+ return autofillId.equals(node.getAutofillId());
+ });
+ }
+
+ private static ViewNode findViewNode(@NonNull AssistStructure structure,
+ @NonNull ViewNodeFilter filter) {
+ final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
+ final int numWindowNodes = structure.getWindowNodeCount();
+ for (int i = 0; i < numWindowNodes; i++) {
+ nodesToProcess.add(structure.getWindowNodeAt(i).getRootViewNode());
+ }
+ while (!nodesToProcess.isEmpty()) {
+ final ViewNode node = nodesToProcess.removeFirst();
+ if (filter.matches(node)) {
+ return node;
+ }
+ for (int i = 0; i < node.getChildCount(); i++) {
+ nodesToProcess.addLast(node.getChildAt(i));
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Sanitize the {@code webDomain} property of the URL bar node on compat mode.
+ */
+ public static void sanitizeUrlBar(@NonNull AssistStructure structure,
+ @NonNull String urlBarId) {
+ final ViewNode urlBarNode = findViewNode(structure, (node) -> {
+ return urlBarId.equals(node.getIdEntry());
+ });
+ if (urlBarNode != null) {
+ final String domain = urlBarNode.getText().toString();
+ if (domain.isEmpty()) {
+ if (sDebug) Slog.d(TAG, "sanitizeUrlBar(): empty on " + urlBarId);
+ return;
+ }
+ urlBarNode.setWebDomain(domain);
+ if (sDebug) {
+ Slog.d(TAG, "sanitizeUrlBar(): id=" + urlBarId + ", domain="
+ + urlBarNode.getWebDomain());
+ }
+ }
+ }
+
+ private interface ViewNodeFilter {
+ boolean matches(ViewNode node);
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4a24704..55c36b0 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -140,6 +140,9 @@
/** Component that's being auto-filled */
@NonNull private final ComponentName mComponentName;
+ /** Whether the app being autofilled is running in compat mode. */
+ private final boolean mCompatMode;
+
@GuardedBy("mLock")
private final ArrayMap<AutofillId, ViewState> mViewStates = new ArrayMap<>();
@@ -263,6 +266,15 @@
componentNameFromApp == null ? "null"
: componentNameFromApp.flattenToShortString()));
}
+ if (mCompatMode) {
+ // Sanitize URL bar, if needed
+ final String urlBarId = mService.getUrlBarResourceIdForCompatModeLocked(
+ mComponentName.getPackageName());
+ if (sDebug) Slog.d(TAG, "url_bar in compat mode: " + urlBarId);
+ if (urlBarId != null) {
+ Helper.sanitizeUrlBar(structure, urlBarId);
+ }
+ }
structure.sanitizeForParceling(true);
// Flags used to start the session.
@@ -476,7 +488,7 @@
@NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
@NonNull LocalLog wtfHistory,
@NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName,
- int flags) {
+ boolean compatMode, int flags) {
id = sessionId;
mFlags = flags;
this.uid = uid;
@@ -491,6 +503,7 @@
mUiLatencyHistory = uiLatencyHistory;
mWtfHistory = wtfHistory;
mComponentName = componentName;
+ mCompatMode = compatMode;
mClient = IAutoFillManagerClient.Stub.asInterface(client);
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
@@ -1537,7 +1550,7 @@
final int numContexts = mContexts.size();
for (int i = numContexts - 1; i >= 0; i--) {
final FillContext context = mContexts.get(i);
- final ViewNode node = context.findViewNodeByAutofillId(id);
+ final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
if (node != null) {
final AutofillValue value = node.getAutofillValue();
if (sDebug) {
@@ -1561,7 +1574,7 @@
for (int i = numContexts - 1; i >= 0; i--) {
final FillContext context = mContexts.get(i);
- final ViewNode node = context.findViewNodeByAutofillId(id);
+ final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
if (node != null && node.getAutofillOptions() != null) {
return node.getAutofillOptions();
}
@@ -2288,6 +2301,7 @@
pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
pw.print(prefix); pw.print("mClientState: "); pw.println(
Helper.bundleToString(mClientState));
+ pw.print(prefix); pw.print("mCompatMode: "); pw.println(mCompatMode);
pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
mRemoteFillService.dump(prefix, pw);
}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index ef82f36..fba0377 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -43,7 +43,10 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
@@ -65,12 +68,13 @@
// There is some accuracy error in wifi reports so allow some slop in the results.
private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750;
- private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor(
- (ThreadFactory) r -> {
- Thread t = new Thread(r, "batterystats-worker");
- t.setPriority(Thread.NORM_PRIORITY);
- return t;
- });
+ private final ScheduledExecutorService mExecutorService =
+ Executors.newSingleThreadScheduledExecutor(
+ (ThreadFactory) r -> {
+ Thread t = new Thread(r, "batterystats-worker");
+ t.setPriority(Thread.NORM_PRIORITY);
+ return t;
+ });
private final Context mContext;
private final BatteryStatsImpl mStats;
@@ -85,8 +89,20 @@
private String mCurrentReason = null;
@GuardedBy("this")
+ private boolean mOnBattery;
+
+ @GuardedBy("this")
+ private boolean mOnBatteryScreenOff;
+
+ @GuardedBy("this")
+ private boolean mUseLatestStates = true;
+
+ @GuardedBy("this")
private final IntArray mUidsToRemove = new IntArray();
+ @GuardedBy("this")
+ private Future<?> mWakelockChangesUpdate;
+
private final Object mWorkerLock = new Object();
@GuardedBy("mWorkerLock")
@@ -157,6 +173,50 @@
return null;
}
+ @Override
+ public Future<?> scheduleCpuSyncDueToScreenStateChange(
+ boolean onBattery, boolean onBatteryScreenOff) {
+ synchronized (BatteryExternalStatsWorker.this) {
+ if (mCurrentFuture == null || (mUpdateFlags & UPDATE_CPU) == 0) {
+ mOnBattery = onBattery;
+ mOnBatteryScreenOff = onBatteryScreenOff;
+ mUseLatestStates = false;
+ }
+ return scheduleSyncLocked("screen-state", UPDATE_CPU);
+ }
+ }
+
+ @Override
+ public Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis) {
+ if (mExecutorService.isShutdown()) {
+ return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown"));
+ }
+
+ if (mWakelockChangesUpdate != null) {
+ // If there's already a scheduled task, leave it as is if we're trying to re-schedule
+ // it again with a delay, otherwise cancel and re-schedule it.
+ if (delayMillis == 0) {
+ mWakelockChangesUpdate.cancel(false);
+ } else {
+ return mWakelockChangesUpdate;
+ }
+ }
+
+ mWakelockChangesUpdate = mExecutorService.schedule(() -> {
+ scheduleSync("wakelock-change", UPDATE_CPU);
+ scheduleRunnable(() -> mStats.postBatteryNeedsCpuUpdateMsg());
+ mWakelockChangesUpdate = null;
+ }, delayMillis, TimeUnit.MILLISECONDS);
+ return mWakelockChangesUpdate;
+ }
+
+ @Override
+ public void cancelCpuSyncDueToWakelockChange() {
+ if (mWakelockChangesUpdate != null) {
+ mWakelockChangesUpdate.cancel(false);
+ }
+ }
+
public synchronized Future<?> scheduleWrite() {
if (mExecutorService.isShutdown()) {
return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown"));
@@ -204,14 +264,21 @@
final int updateFlags;
final String reason;
final int[] uidsToRemove;
+ final boolean onBattery;
+ final boolean onBatteryScreenOff;
+ final boolean useLatestStates;
synchronized (BatteryExternalStatsWorker.this) {
updateFlags = mUpdateFlags;
reason = mCurrentReason;
uidsToRemove = mUidsToRemove.size() > 0 ? mUidsToRemove.toArray() : EmptyArray.INT;
+ onBattery = mOnBattery;
+ onBatteryScreenOff = mOnBatteryScreenOff;
+ useLatestStates = mUseLatestStates;
mUpdateFlags = 0;
mCurrentReason = null;
mUidsToRemove.clear();
mCurrentFuture = null;
+ mUseLatestStates = true;
}
synchronized (mWorkerLock) {
@@ -219,7 +286,8 @@
Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason);
}
try {
- updateExternalStatsLocked(reason, updateFlags);
+ updateExternalStatsLocked(reason, updateFlags, onBattery,
+ onBatteryScreenOff, useLatestStates);
} finally {
if (DEBUG) {
Slog.d(TAG, "end updateExternalStatsSync");
@@ -250,7 +318,8 @@
};
@GuardedBy("mWorkerLock")
- private void updateExternalStatsLocked(final String reason, int updateFlags) {
+ private void updateExternalStatsLocked(final String reason, int updateFlags,
+ boolean onBattery, boolean onBatteryScreenOff, boolean useLatestStates) {
// We will request data from external processes asynchronously, and wait on a timeout.
SynchronousResultReceiver wifiReceiver = null;
SynchronousResultReceiver bluetoothReceiver = null;
@@ -306,7 +375,14 @@
reason, 0);
if ((updateFlags & UPDATE_CPU) != 0) {
- mStats.updateCpuTimeLocked();
+ if (useLatestStates) {
+ onBattery = mStats.isOnBatteryLocked();
+ onBatteryScreenOff = mStats.isOnBatteryScreenOffLocked();
+ }
+ mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff);
+ }
+
+ if ((updateFlags & UPDATE_ALL) != 0) {
mStats.updateKernelWakelocksLocked();
mStats.updateKernelMemoryBandwidthLocked();
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index ea52782..9d1adb2 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1057,7 +1057,7 @@
// to block such a low level service like BatteryService on external stats like WiFi.
mWorker.scheduleRunnable(() -> {
synchronized (mStats) {
- final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE;
+ final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status);
if (mStats.isOnBattery() == onBattery) {
// The battery state has not changed, so we don't need to sync external
// stats immediately.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index fffe7dc..c5424b7 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -551,8 +551,6 @@
// Used to play ringtones outside system_server
private volatile IRingtonePlayer mRingtonePlayer;
- private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
-
// Request to override default use of A2DP for media.
private boolean mBluetoothA2dpEnabled;
private final Object mBluetoothA2dpEnabledLock = new Object();
@@ -571,8 +569,6 @@
AudioSystem.DEVICE_OUT_AUX_LINE;
int mFullVolumeDevices = 0;
- // TODO merge orientation and rotation
- private final boolean mMonitorOrientation;
private final boolean mMonitorRotation;
private boolean mDockAudioMediaEnabled = true;
@@ -788,13 +784,6 @@
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- // TODO merge orientation and rotation
- mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
- if (mMonitorOrientation) {
- Log.v(TAG, "monitoring device orientation");
- // initialize orientation in AudioSystem
- setOrientationForAudioSystem();
- }
mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
if (mMonitorRotation) {
RotationHelper.init(mContext, mAudioHandler);
@@ -963,10 +952,7 @@
// Restore ringer mode
setRingerModeInt(getRingerModeInternal(), false);
- // Reset device orientation (if monitored for this device)
- if (mMonitorOrientation) {
- setOrientationForAudioSystem();
- }
+ // Reset device rotation (if monitored for this device)
if (mMonitorRotation) {
RotationHelper.updateOrientation();
}
@@ -6192,24 +6178,15 @@
// Device orientation
//==========================================================================================
/**
- * Handles device configuration changes that may map to a change in the orientation
- * or orientation.
- * Monitoring orientation and rotation is optional, and is defined by the definition and value
- * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
+ * Handles device configuration changes that may map to a change in rotation.
+ * Monitoring rotation is optional, and is defined by the definition and value
+ * of the "ro.audio.monitorRotation" system property.
*/
private void handleConfigurationChanged(Context context) {
try {
- // reading new orientation "safely" (i.e. under try catch) in case anything
- // goes wrong when obtaining resources and configuration
+ // reading new configuration "safely" (i.e. under try catch) in case anything
+ // goes wrong.
Configuration config = context.getResources().getConfiguration();
- // TODO merge rotation and orientation
- if (mMonitorOrientation) {
- int newOrientation = config.orientation;
- if (newOrientation != mDeviceOrientation) {
- mDeviceOrientation = newOrientation;
- setOrientationForAudioSystem();
- }
- }
sendMsg(mAudioHandler,
MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
SENDMSG_REPLACE,
@@ -6261,30 +6238,6 @@
}
}
- //TODO move to an external "orientation helper" class
- private void setOrientationForAudioSystem() {
- switch (mDeviceOrientation) {
- case Configuration.ORIENTATION_LANDSCAPE:
- //Log.i(TAG, "orientation is landscape");
- AudioSystem.setParameters("orientation=landscape");
- break;
- case Configuration.ORIENTATION_PORTRAIT:
- //Log.i(TAG, "orientation is portrait");
- AudioSystem.setParameters("orientation=portrait");
- break;
- case Configuration.ORIENTATION_SQUARE:
- //Log.i(TAG, "orientation is square");
- AudioSystem.setParameters("orientation=square");
- break;
- case Configuration.ORIENTATION_UNDEFINED:
- //Log.i(TAG, "orientation is undefined");
- AudioSystem.setParameters("orientation=undefined");
- break;
- default:
- Log.e(TAG, "Unknown orientation");
- }
- }
-
// Handles request to override default use of A2DP for media.
// Must be called synchronized on mConnectedDevices
public void setBluetoothA2dpOnInt(boolean on, String eventSource) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 152c910..23a66ba 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -170,11 +170,13 @@
certXml = CertXml.parse(recoveryServiceCertFile);
} catch (CertParsingException e) {
// TODO: Do not use raw key bytes anymore once the other components are updated
- Log.d(TAG, "Failed to parse the cert file", e);
+ Log.d(TAG, "Failed to parse the input as a cert file: " + HexDump.toHexString(
+ recoveryServiceCertFile));
PublicKey publicKey = parseEcPublicKey(recoveryServiceCertFile);
if (mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey) > 0) {
mDatabase.setShouldCreateSnapshot(userId, uid, true);
}
+ Log.d(TAG, "Successfully set the input as the raw public key");
return;
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 44b83d8..0a87097 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1178,7 +1178,7 @@
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
mContext.getResources().getString(R.string.global_action_settings));
return new Notification.Builder(mContext, SystemNotificationChannels.SYSTEM_CHANGES)
- .setSmallIcon(R.drawable.ic_settings)
+ .setSmallIcon(R.drawable.ic_settings_24dp)
.setContentTitle(mContext.getResources().getString(
R.string.zen_upgrade_notification_title))
.setContentText(mContext.getResources().getString(
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ce3f512..8155656 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1766,6 +1766,9 @@
layer += Z_BOOST_BASE;
}
leash.setLayer(layer);
+
+ final DisplayContent dc = getDisplayContent();
+ dc.assignStackOrdering(t);
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f421bf4..2d32c81 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3524,39 +3524,47 @@
@Override
void assignChildLayers(SurfaceControl.Transaction t) {
+ assignStackOrdering(t);
+ for (int i = 0; i < mChildren.size(); i++) {
+ final TaskStack s = mChildren.get(i);
+ s.assignChildLayers(t);
+ }
+ }
+
+ void assignStackOrdering(SurfaceControl.Transaction t) {
final int HOME_STACK_STATE = 0;
final int NORMAL_STACK_STATE = 1;
final int ALWAYS_ON_TOP_STATE = 2;
int layer = 0;
+ int layerForAnimationLayer = 0;
+
for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
for (int i = 0; i < mChildren.size(); i++) {
final TaskStack s = mChildren.get(i);
- if (state == HOME_STACK_STATE && s.isActivityTypeHome()) {
- s.assignLayer(t, layer++);
- } else if (state == NORMAL_STACK_STATE && !s.isActivityTypeHome()
- && !s.isAlwaysOnTop()) {
- s.assignLayer(t, layer++);
- if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
- t.setLayer(mSplitScreenDividerAnchor, layer++);
- }
- } else if (state == ALWAYS_ON_TOP_STATE && s.isAlwaysOnTop()) {
- s.assignLayer(t, layer++);
+ if (state == HOME_STACK_STATE && !s.isActivityTypeHome()) {
+ continue;
+ } else if (state == NORMAL_STACK_STATE && (s.isActivityTypeHome()
+ || s.isAlwaysOnTop())) {
+ continue;
+ } else if (state == ALWAYS_ON_TOP_STATE && !s.isAlwaysOnTop()) {
+ continue;
+ }
+ s.assignLayer(t, layer++);
+ if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
+ t.setLayer(mSplitScreenDividerAnchor, layer++);
+ }
+ if (s.isSelfOrChildAnimating()) {
+ // Ensure the animation layer ends up above the
+ // highest animating stack and no higher.
+ layerForAnimationLayer = layer++;
}
}
- // The appropriate place for App-Transitions to occur is right
- // above all other animations but still below things in the Picture-and-Picture
- // windowing mode.
- if (state == NORMAL_STACK_STATE && mAppAnimationLayer != null) {
- t.setLayer(mAppAnimationLayer, layer++);
- }
}
- for (int i = 0; i < mChildren.size(); i++) {
- final TaskStack s = mChildren.get(i);
- s.assignChildLayers(t);
+ if (mAppAnimationLayer != null) {
+ t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
}
-
}
@Override
@@ -3854,4 +3862,8 @@
super.prepareSurfaces();
}
+
+ void assignStackOrdering(SurfaceControl.Transaction t) {
+ mTaskStackContainers.assignStackOrdering(t);
+ }
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 97a2954..e4edeb87 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -24,15 +24,15 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.WindowConfiguration;
-import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.view.IRecentsAnimationController;
@@ -41,6 +41,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import com.google.android.collect.Sets;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -99,17 +100,13 @@
final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
final Task task = adapter.mTask;
if (task.mTaskId == taskId) {
- // TODO: Save this screenshot as the task snapshot?
- final Rect taskFrame = new Rect();
- task.getBounds(taskFrame);
- final GraphicBuffer buffer = SurfaceControl.captureLayers(
- task.getSurfaceControl().getHandle(), taskFrame, 1f);
- final AppWindowToken topChild = task.getTopChild();
- final WindowState mainWindow = topChild.findMainWindow();
- return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
- mainWindow.mContentInsets,
- ActivityManager.isLowRamDeviceStatic() /* reduced */,
- 1.0f /* scale */);
+ final TaskSnapshotController snapshotController =
+ mService.mTaskSnapshotController;
+ final ArraySet<Task> tasks = Sets.newArraySet(task);
+ snapshotController.snapshotTasks(tasks);
+ snapshotController.addSkipClosingAppSnapshotTasks(tasks);
+ return snapshotController.getSnapshot(taskId, 0 /* userId */,
+ false /* restoreFromDisk */, false /* reducedResolution */);
}
}
return null;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index a7a2b53..3d7b32c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -92,6 +92,7 @@
private final TaskSnapshotPersister mPersister = new TaskSnapshotPersister(
Environment::getDataSystemCeDirectory);
private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister);
+ private final ArraySet<Task> mSkipClosingAppSnapshotTasks = new ArraySet<>();
private final ArraySet<Task> mTmpTasks = new ArraySet<>();
private final Handler mHandler = new Handler();
@@ -149,10 +150,20 @@
// either closing or hidden.
getClosingTasks(closingApps, mTmpTasks);
snapshotTasks(mTmpTasks);
-
+ mSkipClosingAppSnapshotTasks.clear();
}
- private void snapshotTasks(ArraySet<Task> tasks) {
+ /**
+ * Adds the given {@param tasks} to the list of tasks which should not have their snapshots
+ * taken upon the next processing of the set of closing apps. The caller is responsible for
+ * calling {@link #snapshotTasks} to ensure that the task has an up-to-date snapshot.
+ */
+ @VisibleForTesting
+ void addSkipClosingAppSnapshotTasks(ArraySet<Task> tasks) {
+ mSkipClosingAppSnapshotTasks.addAll(tasks);
+ }
+
+ void snapshotTasks(ArraySet<Task> tasks) {
for (int i = tasks.size() - 1; i >= 0; i--) {
final Task task = tasks.valueAt(i);
final int mode = getSnapshotMode(task);
@@ -295,7 +306,7 @@
// If the task of the app is not visible anymore, it means no other app in that task
// is opening. Thus, the task is closing.
- if (task != null && !task.isVisible()) {
+ if (task != null && !task.isVisible() && !mSkipClosingAppSnapshotTasks.contains(task)) {
outClosingTasks.add(task);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index fa4474b..93e9137 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1129,7 +1129,7 @@
scheduleAnimation();
}
- private void reassignLayer(Transaction t) {
+ void reassignLayer(Transaction t) {
final WindowContainer parent = getParent();
if (parent != null) {
parent.assignChildLayers(t);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 72f95fb..0b03281 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -41,6 +41,7 @@
"com_android_server_tv_TvUinputBridge.cpp",
"com_android_server_tv_TvInputHal.cpp",
"com_android_server_vr_VrManagerService.cpp",
+ "com_android_server_UsbAlsaJackDetector.cpp",
"com_android_server_UsbDeviceManager.cpp",
"com_android_server_UsbDescriptorParser.cpp",
"com_android_server_UsbMidiDevice.cpp",
@@ -97,6 +98,7 @@
"libgui",
"libusbhost",
"libsuspend",
+ "libtinyalsa",
"libEGL",
"libGLESv2",
"libnetutils",
diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
new file mode 100644
index 0000000..e9d4482
--- /dev/null
+++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "UsbAlsaJackDetectorJNI"
+#include "utils/Log.h"
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <asm/byteorder.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#define DRIVER_NAME "/dev/usb_accessory"
+
+#define USB_IN_JACK_NAME "USB in Jack"
+#define USB_OUT_JACK_NAME "USB out Jack"
+
+namespace android
+{
+
+static jboolean is_jack_connected(jint card, const char* control) {
+ struct mixer* card_mixer = mixer_open(card);
+ if (card_mixer == NULL) {
+ return true;
+ }
+ struct mixer_ctl* ctl = mixer_get_ctl_by_name(card_mixer, control);
+ if (!ctl) {
+ return true;
+ }
+ mixer_ctl_update(ctl);
+ int val = mixer_ctl_get_value(ctl, 0);
+ ALOGI("JACK %s - value %d\n", control, val);
+ mixer_close(card_mixer);
+
+ return val != 0;
+}
+
+static jboolean android_server_UsbAlsaJackDetector_hasJackDetect(JNIEnv* /* env */,
+ jobject /* thiz */,
+ jint card)
+{
+ struct mixer* card_mixer = mixer_open(card);
+ if (card_mixer == NULL) {
+ return false;
+ }
+
+ jboolean has_jack = false;
+ if ((mixer_get_ctl_by_name(card_mixer, USB_IN_JACK_NAME) != NULL) ||
+ (mixer_get_ctl_by_name(card_mixer, USB_OUT_JACK_NAME) != NULL)) {
+ has_jack = true;
+ }
+ mixer_close(card_mixer);
+ return has_jack;
+}
+
+
+static jboolean android_server_UsbAlsaJackDetector_inputJackConnected(JNIEnv* /* env */,
+ jobject /* thiz */,
+ jint card)
+{
+ return is_jack_connected(card, USB_IN_JACK_NAME);
+}
+
+
+static jboolean android_server_UsbAlsaJackDetector_outputJackConnected(JNIEnv* /* env */,
+ jobject /* thiz */,
+ jint card)
+{
+ return is_jack_connected(card, USB_OUT_JACK_NAME);
+}
+
+static void android_server_UsbAlsaJackDetector_jackDetect(JNIEnv* env,
+ jobject thiz,
+ jint card) {
+ jclass jdclass = env->GetObjectClass(thiz);
+ jmethodID method_jackDetectCallback = env->GetMethodID(jdclass, "jackDetectCallback", "()Z");
+ if (method_jackDetectCallback == NULL) {
+ ALOGE("Can't find jackDetectCallback");
+ return;
+ }
+
+ struct mixer* m = mixer_open(card);
+ if (!m) {
+ ALOGE("Jack detect unable to open mixer\n");
+ return;
+ }
+ mixer_subscribe_events(m, 1);
+ do {
+
+ // Wait for a mixer event. Retry if interrupted, exit on error.
+ int retval;
+ do {
+ retval = mixer_wait_event(m, -1);
+ } while (retval == -EINTR);
+ if (retval < 0) {
+ break;
+ }
+ mixer_consume_event(m);
+ } while (env->CallBooleanMethod(thiz, method_jackDetectCallback));
+
+ mixer_close(m);
+ return;
+}
+
+static const JNINativeMethod method_table[] = {
+ { "nativeHasJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_hasJackDetect },
+ { "nativeInputJackConnected", "(I)Z",
+ (void*)android_server_UsbAlsaJackDetector_inputJackConnected },
+ { "nativeOutputJackConnected", "(I)Z",
+ (void*)android_server_UsbAlsaJackDetector_outputJackConnected },
+ { "nativeJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_jackDetect },
+};
+
+int register_android_server_UsbAlsaJackDetector(JNIEnv *env)
+{
+ jclass clazz = env->FindClass("com/android/server/usb/UsbAlsaJackDetector");
+ if (clazz == NULL) {
+ ALOGE("Can't find com/android/server/usb/UsbAlsaJackDetector");
+ return -1;
+ }
+
+ if (!jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaJackDetector",
+ method_table, NELEM(method_table))) {
+ ALOGE("Can't register UsbAlsaJackDetector native methods");
+ return -1;
+ }
+
+ return 0;
+}
+
+}
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index bf2a637..0ebef37 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -34,6 +34,7 @@
int register_android_server_storage_AppFuse(JNIEnv* env);
int register_android_server_SerialService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
+int register_android_server_UsbAlsaJackDetector(JNIEnv* env);
int register_android_server_UsbDeviceManager(JNIEnv* env);
int register_android_server_UsbMidiDevice(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
@@ -82,6 +83,7 @@
register_android_server_AlarmManagerService(env);
register_android_server_UsbDeviceManager(env);
register_android_server_UsbMidiDevice(env);
+ register_android_server_UsbAlsaJackDetector(env);
register_android_server_UsbHostManager(env);
register_android_server_vr_VrManagerService(env);
register_android_server_VibratorService(env);
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index 6e1808b..28b54ef 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -323,6 +323,7 @@
private void turnBatteryOn() throws Exception {
executeCommand("cmd battery unplug");
+ executeCommand("cmd battery set status " + BatteryManager.BATTERY_STATUS_NOT_CHARGING);
assertBatteryOn();
}
@@ -336,6 +337,7 @@
private void turnBatteryOff() throws Exception {
executeCommand("cmd battery set ac " + BatteryManager.BATTERY_PLUGGED_AC);
+ executeCommand("cmd battery set status " + BatteryManager.BATTERY_STATUS_CHARGING);
}
private static void batteryReset() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 78b6077..cbbdca6 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -308,6 +308,7 @@
private void reportEvent(AppStandbyController controller, int eventType,
long elapsedTime) {
// Back to ACTIVE on event
+ mInjector.mElapsedRealtime = elapsedTime;
UsageEvents.Event ev = new UsageEvents.Event();
ev.mPackage = PACKAGE_1;
ev.mEventType = eventType;
@@ -487,6 +488,89 @@
}
@Test
+ public void testCascadingTimeouts() throws Exception {
+ setChargingState(mController, false);
+
+ reportEvent(mController, USER_INTERACTION, 0);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ reportEvent(mController, NOTIFICATION_SEEN, 1000);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
+ REASON_PREDICTED, 1000);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+ REASON_PREDICTED, 2000 + mController.mStrongUsageTimeoutMillis);
+ assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+ REASON_PREDICTED, 2000 + mController.mNotificationSeenTimeoutMillis);
+ assertBucket(STANDBY_BUCKET_FREQUENT);
+ }
+
+ @Test
+ public void testOverlappingTimeouts() throws Exception {
+ setChargingState(mController, false);
+
+ reportEvent(mController, USER_INTERACTION, 0);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ reportEvent(mController, NOTIFICATION_SEEN, 1000);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ // Overlapping USER_INTERACTION before previous one times out
+ reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ // Still in ACTIVE after first USER_INTERACTION times out
+ mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000;
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+ REASON_PREDICTED, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ // Both timed out, so NOTIFICATION_SEEN timeout should be effective
+ mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000;
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+ REASON_PREDICTED, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+ mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000;
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
+ REASON_PREDICTED, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_RARE);
+ }
+
+ @Test
+ public void testPredictionNotOverridden() throws Exception {
+ setChargingState(mController, false);
+
+ reportEvent(mController, USER_INTERACTION, 0);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000;
+ reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ // Falls back to WORKING_SET
+ mInjector.mElapsedRealtime += 5000;
+ mController.checkIdleStates(USER_ID);
+ assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+ // Predict to ACTIVE
+ mInjector.mElapsedRealtime += 1000;
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+ REASON_PREDICTED, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ // CheckIdleStates should not change the prediction
+ mInjector.mElapsedRealtime += 1000;
+ mController.checkIdleStates(USER_ID);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+ }
+
+ @Test
public void testAddActiveDeviceAdmin() {
assertActiveAdmins(USER_ID, (String[]) null);
assertActiveAdmins(USER_ID2, (String[]) null);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 920796e..5650050 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -29,6 +29,7 @@
import android.support.test.runner.AndroidJUnit4;
import android.util.ArraySet;
+import com.google.android.collect.Sets;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -74,6 +75,21 @@
}
@Test
+ public void testGetClosingApps_skipClosingAppsSnapshotTasks() throws Exception {
+ final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
+ "closingWindow");
+ closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
+ true /* performLayout */, false /* isVoiceInteraction */);
+ final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
+ closingApps.add(closingWindow.mAppToken);
+ final ArraySet<Task> closingTasks = new ArraySet<>();
+ sWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(
+ Sets.newArraySet(closingWindow.mAppToken.getTask()));
+ sWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
+ assertEquals(0, closingTasks.size());
+ }
+
+ @Test
public void testGetSnapshotMode() throws Exception {
final WindowState disabledWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index b654a66..f26c2ae 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -23,6 +23,7 @@
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
import android.app.usage.UsageStatsManager;
import android.os.SystemClock;
@@ -87,7 +88,9 @@
// The last time a job was run for this app
private static final String ATTR_LAST_RUN_JOB_TIME = "lastJobRunTime";
// The time when the forced active state can be overridden.
- private static final String ATTR_BUCKET_TIMEOUT_TIME = "bucketTimeoutTime";
+ private static final String ATTR_BUCKET_ACTIVE_TIMEOUT_TIME = "activeTimeoutTime";
+ // The time when the forced working_set state can be overridden.
+ private static final String ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME = "workingSetTimeoutTime";
// device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
@@ -117,11 +120,15 @@
int lastInformedBucket;
// The last time a job was run for this app, using elapsed timebase
long lastJobRunTime;
- // When should the bucket state timeout, in elapsed timebase, if greater than
+ // When should the bucket active state timeout, in elapsed timebase, if greater than
// lastUsedElapsedTime.
// This is used to keep the app in a high bucket regardless of other timeouts and
// predictions.
- long bucketTimeoutTime;
+ long bucketActiveTimeoutTime;
+ // If there's a forced working_set state, this is when it times out. This can be sitting
+ // under any active state timeout, so that it becomes applicable after the active state
+ // timeout expires.
+ long bucketWorkingSetTimeoutTime;
}
AppIdleHistory(File storageDir, long elapsedRealtime) {
@@ -208,11 +215,28 @@
* @param packageName name of the app being updated, for logging purposes
* @param newBucket the bucket to set the app to
* @param elapsedRealtime mark as used time if non-zero
- * @param timeout set the timeout of the specified bucket, if non-zero
+ * @param timeout set the timeout of the specified bucket, if non-zero. Can only be used
+ * with bucket values of ACTIVE and WORKING_SET.
* @return
*/
public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName,
int newBucket, long elapsedRealtime, long timeout) {
+ // Set the timeout if applicable
+ if (timeout > elapsedRealtime) {
+ // Convert to elapsed timebase
+ final long timeoutTime = mElapsedDuration + (timeout - mElapsedSnapshot);
+ if (newBucket == STANDBY_BUCKET_ACTIVE) {
+ appUsageHistory.bucketActiveTimeoutTime = Math.max(timeoutTime,
+ appUsageHistory.bucketActiveTimeoutTime);
+ } else if (newBucket == STANDBY_BUCKET_WORKING_SET) {
+ appUsageHistory.bucketWorkingSetTimeoutTime = Math.max(timeoutTime,
+ appUsageHistory.bucketWorkingSetTimeoutTime);
+ } else {
+ throw new IllegalArgumentException("Cannot set a timeout on bucket=" +
+ newBucket);
+ }
+ }
+
if (elapsedRealtime != 0) {
appUsageHistory.lastUsedElapsedTime = mElapsedDuration
+ (elapsedRealtime - mElapsedSnapshot);
@@ -226,12 +250,6 @@
.currentBucket
+ ", reason=" + appUsageHistory.bucketingReason);
}
- if (timeout > elapsedRealtime) {
- // Convert to elapsed timebase
- appUsageHistory.bucketTimeoutTime =
- Math.max(appUsageHistory.bucketTimeoutTime,
- mElapsedDuration + (timeout - mElapsedSnapshot));
- }
}
appUsageHistory.bucketingReason = REASON_USAGE;
@@ -247,7 +265,8 @@
* @param userId
* @param newBucket the bucket to set the app to
* @param elapsedRealtime mark as used time if non-zero
- * @param timeout set the timeout of the specified bucket, if non-zero
+ * @param timeout set the timeout of the specified bucket, if non-zero. Can only be used
+ * with bucket values of ACTIVE and WORKING_SET.
* @return
*/
public AppUsageHistory reportUsage(String packageName, int userId, int newBucket,
@@ -504,8 +523,10 @@
parser.getAttributeValue(null, ATTR_BUCKETING_REASON);
appUsageHistory.lastJobRunTime = getLongValue(parser,
ATTR_LAST_RUN_JOB_TIME, Long.MIN_VALUE);
- appUsageHistory.bucketTimeoutTime = getLongValue(parser,
- ATTR_BUCKET_TIMEOUT_TIME, 0L);
+ appUsageHistory.bucketActiveTimeoutTime = getLongValue(parser,
+ ATTR_BUCKET_ACTIVE_TIMEOUT_TIME, 0L);
+ appUsageHistory.bucketWorkingSetTimeoutTime = getLongValue(parser,
+ ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME, 0L);
if (appUsageHistory.bucketingReason == null) {
appUsageHistory.bucketingReason = REASON_DEFAULT;
}
@@ -557,9 +578,13 @@
xml.attribute(null, ATTR_CURRENT_BUCKET,
Integer.toString(history.currentBucket));
xml.attribute(null, ATTR_BUCKETING_REASON, history.bucketingReason);
- if (history.bucketTimeoutTime > 0) {
- xml.attribute(null, ATTR_BUCKET_TIMEOUT_TIME, Long.toString(history
- .bucketTimeoutTime));
+ if (history.bucketActiveTimeoutTime > 0) {
+ xml.attribute(null, ATTR_BUCKET_ACTIVE_TIMEOUT_TIME, Long.toString(history
+ .bucketActiveTimeoutTime));
+ }
+ if (history.bucketWorkingSetTimeoutTime > 0) {
+ xml.attribute(null, ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME, Long.toString(history
+ .bucketWorkingSetTimeoutTime));
}
if (history.lastJobRunTime != Long.MIN_VALUE) {
xml.attribute(null, ATTR_LAST_RUN_JOB_TIME, Long.toString(history
@@ -593,14 +618,19 @@
continue;
}
idpw.print("package=" + packageName);
+ idpw.print(" userId=" + userId);
idpw.print(" lastUsedElapsed=");
TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw);
idpw.print(" lastUsedScreenOn=");
TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
idpw.print(" lastPredictedTime=");
TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastPredictedTime, idpw);
- idpw.print(" bucketTimeoutTime=");
- TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketTimeoutTime, idpw);
+ idpw.print(" bucketActiveTimeoutTime=");
+ TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketActiveTimeoutTime,
+ idpw);
+ idpw.print(" bucketWorkingSetTimeoutTime=");
+ TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketWorkingSetTimeoutTime,
+ idpw);
idpw.print(" lastJobRunTime=");
TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastJobRunTime, idpw);
idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 32db752..c31809e 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -30,6 +30,7 @@
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.usage.UsageStatsManager.StandbyBuckets;
@@ -171,6 +172,8 @@
static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
static final int MSG_PAROLE_STATE_CHANGED = 9;
static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
+ /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
+ static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
long mCheckIdleIntervalMillis;
long mAppIdleParoleIntervalMillis;
@@ -322,7 +325,7 @@
// Get sync adapters for the authority
String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
authority, userId);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mInjector.elapsedRealtime();
for (String packageName: packages) {
// Only force the sync adapters to active if the provider is not in the same package and
// the sync adapter is a system package.
@@ -460,53 +463,8 @@
for (int p = 0; p < packageCount; p++) {
final PackageInfo pi = packages.get(p);
final String packageName = pi.packageName;
- final boolean isSpecial = isAppSpecial(packageName,
- UserHandle.getAppId(pi.applicationInfo.uid),
- userId);
- if (DEBUG) {
- Slog.d(TAG, " Checking idle state for " + packageName + " special=" +
- isSpecial);
- }
- if (isSpecial) {
- synchronized (mAppIdleLock) {
- mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime,
- STANDBY_BUCKET_EXEMPTED, REASON_DEFAULT);
- }
- maybeInformListeners(packageName, userId, elapsedRealtime,
- STANDBY_BUCKET_EXEMPTED, false);
- } else {
- synchronized (mAppIdleLock) {
- AppIdleHistory.AppUsageHistory app =
- mAppIdleHistory.getAppUsageHistory(packageName,
- userId, elapsedRealtime);
- // If the bucket was forced by the developer or the app is within the
- // temporary active period, leave it alone.
- if (REASON_FORCED.equals(app.bucketingReason)
- || !hasBucketTimeoutPassed(app, elapsedRealtime)) {
- continue;
- }
- boolean predictionLate = false;
- // If the bucket was moved up due to usage, let the timeouts apply.
- if (REASON_DEFAULT.equals(app.bucketingReason)
- || REASON_USAGE.equals(app.bucketingReason)
- || REASON_TIMEOUT.equals(app.bucketingReason)
- || (predictionLate = predictionTimedOut(app, elapsedRealtime))) {
- int oldBucket = app.currentBucket;
- int newBucket = getBucketForLocked(packageName, userId,
- elapsedRealtime);
- if (DEBUG) {
- Slog.d(TAG, " Old bucket=" + oldBucket
- + ", newBucket=" + newBucket);
- }
- if (oldBucket < newBucket || predictionLate) {
- mAppIdleHistory.setAppStandbyBucket(packageName, userId,
- elapsedRealtime, newBucket, REASON_TIMEOUT);
- maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket, false);
- }
- }
- }
- }
+ checkAndUpdateStandbyState(packageName, userId, pi.applicationInfo.uid,
+ elapsedRealtime);
}
}
if (DEBUG) {
@@ -516,6 +474,90 @@
return true;
}
+ /** Check if we need to update the standby state of a specific app. */
+ private void checkAndUpdateStandbyState(String packageName, @UserIdInt int userId,
+ int uid, long elapsedRealtime) {
+ if (uid <= 0) {
+ try {
+ uid = mPackageManager.getPackageUidAsUser(packageName, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Not a valid package for this user, nothing to do
+ // TODO: Remove any history of removed packages
+ return;
+ }
+ }
+ final boolean isSpecial = isAppSpecial(packageName,
+ UserHandle.getAppId(uid),
+ userId);
+ if (DEBUG) {
+ Slog.d(TAG, " Checking idle state for " + packageName + " special=" +
+ isSpecial);
+ }
+ if (isSpecial) {
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime,
+ STANDBY_BUCKET_EXEMPTED, REASON_DEFAULT);
+ }
+ maybeInformListeners(packageName, userId, elapsedRealtime,
+ STANDBY_BUCKET_EXEMPTED, false);
+ } else {
+ synchronized (mAppIdleLock) {
+ final AppIdleHistory.AppUsageHistory app =
+ mAppIdleHistory.getAppUsageHistory(packageName,
+ userId, elapsedRealtime);
+ String reason = app.bucketingReason;
+
+ // If the bucket was forced by the user/developer, leave it alone.
+ // A usage event will be the only way to bring it out of this forced state
+ if (REASON_FORCED.equals(app.bucketingReason)) {
+ return;
+ }
+ final int oldBucket = app.currentBucket;
+ int newBucket = Math.max(oldBucket, STANDBY_BUCKET_ACTIVE); // Undo EXEMPTED
+ boolean predictionLate = false;
+ // Compute age-based bucket
+ if (REASON_DEFAULT.equals(app.bucketingReason)
+ || REASON_USAGE.equals(app.bucketingReason)
+ || REASON_TIMEOUT.equals(app.bucketingReason)
+ || (predictionLate = predictionTimedOut(app, elapsedRealtime))) {
+ newBucket = getBucketForLocked(packageName, userId,
+ elapsedRealtime);
+ if (DEBUG) {
+ Slog.d(TAG, "Evaluated AOSP newBucket = " + newBucket);
+ }
+ reason = REASON_TIMEOUT;
+ }
+ // Check if the app is within one of the timeouts for forced bucket elevation
+ final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime);
+ if (newBucket >= STANDBY_BUCKET_ACTIVE
+ && app.bucketActiveTimeoutTime > elapsedTimeAdjusted) {
+ newBucket = STANDBY_BUCKET_ACTIVE;
+ reason = REASON_USAGE;
+ if (DEBUG) {
+ Slog.d(TAG, " Keeping at ACTIVE due to min timeout");
+ }
+ } else if (newBucket >= STANDBY_BUCKET_WORKING_SET
+ && app.bucketWorkingSetTimeoutTime > elapsedTimeAdjusted) {
+ newBucket = STANDBY_BUCKET_WORKING_SET;
+ reason = REASON_USAGE;
+ if (DEBUG) {
+ Slog.d(TAG, " Keeping at WORKING_SET due to min timeout");
+ }
+ }
+ if (DEBUG) {
+ Slog.d(TAG, " Old bucket=" + oldBucket
+ + ", newBucket=" + newBucket);
+ }
+ if (oldBucket < newBucket || predictionLate) {
+ mAppIdleHistory.setAppStandbyBucket(packageName, userId,
+ elapsedRealtime, newBucket, reason);
+ maybeInformListeners(packageName, userId, elapsedRealtime,
+ newBucket, false);
+ }
+ }
+ }
+ }
+
private boolean predictionTimedOut(AppIdleHistory.AppUsageHistory app, long elapsedRealtime) {
return app.bucketingReason != null
&& app.bucketingReason.startsWith(REASON_PREDICTED)
@@ -526,7 +568,9 @@
private boolean hasBucketTimeoutPassed(AppIdleHistory.AppUsageHistory app,
long elapsedRealtime) {
- return app.bucketTimeoutTime < mAppIdleHistory.getElapsedTime(elapsedRealtime);
+ final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime);
+ return app.bucketActiveTimeoutTime < elapsedTimeAdjusted
+ && app.bucketWorkingSetTimeoutTime < elapsedTimeAdjusted;
}
private void maybeInformListeners(String packageName, int userId,
@@ -631,16 +675,22 @@
event.mPackage, userId, elapsedRealtime);
final int prevBucket = appHistory.currentBucket;
final String prevBucketReason = appHistory.bucketingReason;
+ final long nextCheckTime;
if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
+ // Mild usage elevates to WORKING_SET but doesn't change usage time.
mAppIdleHistory.reportUsage(appHistory, event.mPackage,
STANDBY_BUCKET_WORKING_SET,
- elapsedRealtime, elapsedRealtime + mNotificationSeenTimeoutMillis);
+ 0, elapsedRealtime + mNotificationSeenTimeoutMillis);
+ nextCheckTime = mNotificationSeenTimeoutMillis;
} else {
- mAppIdleHistory.reportUsage(event.mPackage, userId,
+ mAppIdleHistory.reportUsage(appHistory, event.mPackage,
STANDBY_BUCKET_ACTIVE,
elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis);
+ nextCheckTime = mStrongUsageTimeoutMillis;
}
-
+ mHandler.sendMessageDelayed(mHandler.obtainMessage
+ (MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, event.mPackage),
+ nextCheckTime);
final boolean userStartedInteracting =
appHistory.currentBucket == STANDBY_BUCKET_ACTIVE &&
prevBucket != appHistory.currentBucket &&
@@ -932,9 +982,24 @@
// If the bucket is required to stay in a higher state for a specified duration, don't
// override unless the duration has passed
- if (predicted && app.currentBucket < newBucket
- && !hasBucketTimeoutPassed(app, elapsedRealtime)) {
- return;
+ if (predicted) {
+ // Check if the app is within one of the timeouts for forced bucket elevation
+ final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime);
+ if (newBucket > STANDBY_BUCKET_ACTIVE
+ && app.bucketActiveTimeoutTime > elapsedTimeAdjusted) {
+ newBucket = STANDBY_BUCKET_ACTIVE;
+ reason = REASON_USAGE;
+ if (DEBUG) {
+ Slog.d(TAG, " Keeping at ACTIVE due to min timeout");
+ }
+ } else if (newBucket > STANDBY_BUCKET_WORKING_SET
+ && app.bucketWorkingSetTimeoutTime > elapsedTimeAdjusted) {
+ newBucket = STANDBY_BUCKET_WORKING_SET;
+ reason = REASON_USAGE;
+ if (DEBUG) {
+ Slog.d(TAG, " Keeping at WORKING_SET due to min timeout");
+ }
+ }
}
mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
@@ -1347,6 +1412,10 @@
+ ", Charging state:" + mCharging);
informParoleStateChanged();
break;
+ case MSG_CHECK_PACKAGE_IDLE_STATE:
+ checkAndUpdateStandbyState((String) msg.obj, msg.arg1, msg.arg2,
+ mInjector.elapsedRealtime());
+ break;
default:
super.handleMessage(msg);
break;
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
index 7480e56..9d4db00 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
@@ -17,9 +17,14 @@
package com.android.server.usb;
import android.annotation.NonNull;
+import android.media.AudioSystem;
+import android.media.IAudioService;
+import android.os.RemoteException;
import android.service.usb.UsbAlsaDeviceProto;
+import android.util.Slog;
import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.audio.AudioService;
/**
* Represents the ALSA specification, and attributes of an ALSA device.
@@ -30,25 +35,31 @@
private final int mCardNum;
private final int mDeviceNum;
- private final boolean mHasPlayback;
- private final boolean mHasCapture;
+ private final String mDeviceAddress;
+ private final boolean mHasOutput;
+ private final boolean mHasInput;
private final boolean mIsInputHeadset;
private final boolean mIsOutputHeadset;
- private final String mDeviceAddress;
+ private boolean mSelected = false;
+ private int mOutputState;
+ private int mInputState;
+ private UsbAlsaJackDetector mJackDetector;
+ private IAudioService mAudioService;
private String mDeviceName = "";
private String mDeviceDescription = "";
- public UsbAlsaDevice(int card, int device, String deviceAddress,
- boolean hasPlayback, boolean hasCapture,
+ public UsbAlsaDevice(IAudioService audioService, int card, int device, String deviceAddress,
+ boolean hasOutput, boolean hasInput,
boolean isInputHeadset, boolean isOutputHeadset) {
+ mAudioService = audioService;
mCardNum = card;
mDeviceNum = device;
mDeviceAddress = deviceAddress;
- mHasPlayback = hasPlayback;
- mHasCapture = hasCapture;
+ mHasOutput = hasOutput;
+ mHasInput = hasInput;
mIsInputHeadset = isInputHeadset;
mIsOutputHeadset = isOutputHeadset;
}
@@ -75,71 +86,187 @@
}
/**
- * @returns true if the device supports playback.
+ * @returns the ALSA card/device address string.
*/
- public boolean hasPlayback() {
- return mHasPlayback;
+ public String getAlsaCardDeviceString() {
+ if (mCardNum < 0 || mDeviceNum < 0) {
+ Slog.e(TAG, "Invalid alsa card or device alsaCard: " + mCardNum
+ + " alsaDevice: " + mDeviceNum);
+ return null;
+ }
+ return AudioService.makeAlsaAddressString(mCardNum, mDeviceNum);
}
/**
- * @returns true if the device supports capture (recording).
+ * @returns true if the device supports output.
*/
- public boolean hasCapture() {
- return mHasCapture;
+ public boolean hasOutput() {
+ return mHasOutput;
}
/**
- * @returns true if the device is a headset for purposes of capture.
+ * @returns true if the device supports input (recording).
+ */
+ public boolean hasInput() {
+ return mHasInput;
+ }
+
+ /**
+ * @returns true if the device is a headset for purposes of input.
*/
public boolean isInputHeadset() {
return mIsInputHeadset;
}
/**
- * @returns true if the device is a headset for purposes of playback.
+ * @returns true if the device is a headset for purposes of output.
*/
public boolean isOutputHeadset() {
return mIsOutputHeadset;
}
/**
+ * @returns true if input jack is detected or jack detection is not supported.
+ */
+ private synchronized boolean isInputJackConnected() {
+ if (mJackDetector == null) {
+ return true; // If jack detect isn't supported, say it's connected.
+ }
+ return mJackDetector.isInputJackConnected();
+ }
+
+ /**
+ * @returns true if input jack is detected or jack detection is not supported.
+ */
+ private synchronized boolean isOutputJackConnected() {
+ if (mJackDetector == null) {
+ return true; // if jack detect isn't supported, say it's connected.
+ }
+ return mJackDetector.isOutputJackConnected();
+ }
+
+ /** Begins a jack-detection thread. */
+ private synchronized void startJackDetect() {
+ // If no jack detect capabilities exist, mJackDetector will be null.
+ mJackDetector = UsbAlsaJackDetector.startJackDetect(this);
+ }
+
+ /** Stops a jack-detection thread. */
+ private synchronized void stopJackDetect() {
+ if (mJackDetector != null) {
+ mJackDetector.pleaseStop();
+ }
+ mJackDetector = null;
+ }
+
+ /** Start using this device as the selected USB Audio Device. */
+ public synchronized void start() {
+ mSelected = true;
+ mInputState = 0;
+ mOutputState = 0;
+ startJackDetect();
+ updateWiredDeviceConnectionState(true);
+ }
+
+ /** Stop using this device as the selected USB Audio Device. */
+ public synchronized void stop() {
+ stopJackDetect();
+ updateWiredDeviceConnectionState(false);
+ mSelected = false;
+ }
+
+ /** Updates AudioService with the connection state of the alsaDevice.
+ * Checks ALSA Jack state for inputs and outputs before reporting.
+ */
+ public synchronized void updateWiredDeviceConnectionState(boolean enable) {
+ if (!mSelected) {
+ Slog.e(TAG, "updateWiredDeviceConnectionState on unselected AlsaDevice!");
+ return;
+ }
+ String alsaCardDeviceString = getAlsaCardDeviceString();
+ if (alsaCardDeviceString == null) {
+ return;
+ }
+ try {
+ // Output Device
+ if (mHasOutput) {
+ int device = mIsOutputHeadset
+ ? AudioSystem.DEVICE_OUT_USB_HEADSET
+ : AudioSystem.DEVICE_OUT_USB_DEVICE;
+ if (DEBUG) {
+ Slog.d(TAG, "pre-call device:0x" + Integer.toHexString(device)
+ + " addr:" + alsaCardDeviceString
+ + " name:" + mDeviceName);
+ }
+ boolean connected = isOutputJackConnected();
+ Slog.i(TAG, "OUTPUT JACK connected: " + connected);
+ int outputState = (enable && connected) ? 1 : 0;
+ if (outputState != mOutputState) {
+ mOutputState = outputState;
+ mAudioService.setWiredDeviceConnectionState(device, outputState,
+ alsaCardDeviceString,
+ mDeviceName, TAG);
+ }
+ }
+
+ // Input Device
+ if (mHasInput) {
+ int device = mIsInputHeadset ? AudioSystem.DEVICE_IN_USB_HEADSET
+ : AudioSystem.DEVICE_IN_USB_DEVICE;
+ boolean connected = isInputJackConnected();
+ Slog.i(TAG, "INPUT JACK connected: " + connected);
+ int inputState = (enable && connected) ? 1 : 0;
+ if (inputState != mInputState) {
+ mInputState = inputState;
+ mAudioService.setWiredDeviceConnectionState(
+ device, inputState, alsaCardDeviceString,
+ mDeviceName, TAG);
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
+ }
+ }
+
+
+ /**
* @Override
* @returns a string representation of the object.
*/
- public String toString() {
+ public synchronized String toString() {
return "UsbAlsaDevice: [card: " + mCardNum
+ ", device: " + mDeviceNum
+ ", name: " + mDeviceName
- + ", hasPlayback: " + mHasPlayback
- + ", hasCapture: " + mHasCapture + "]";
+ + ", hasOutput: " + mHasOutput
+ + ", hasInput: " + mHasInput + "]";
}
/**
* Write a description of the device to a dump stream.
*/
- public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+ public synchronized void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
long token = dump.start(idName, id);
dump.write("card", UsbAlsaDeviceProto.CARD, mCardNum);
dump.write("device", UsbAlsaDeviceProto.DEVICE, mDeviceNum);
dump.write("name", UsbAlsaDeviceProto.NAME, mDeviceName);
- dump.write("has_playback", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasPlayback);
- dump.write("has_capture", UsbAlsaDeviceProto.HAS_CAPTURE, mHasCapture);
+ dump.write("has_output", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasOutput);
+ dump.write("has_input", UsbAlsaDeviceProto.HAS_CAPTURE, mHasInput);
dump.write("address", UsbAlsaDeviceProto.ADDRESS, mDeviceAddress);
dump.end(token);
}
// called by logDevices
- String toShortString() {
+ synchronized String toShortString() {
return "[card:" + mCardNum + " device:" + mDeviceNum + " " + mDeviceName + "]";
}
- String getDeviceName() {
+ synchronized String getDeviceName() {
return mDeviceName;
}
- void setDeviceNameAndDescription(String deviceName, String deviceDescription) {
+ synchronized void setDeviceNameAndDescription(String deviceName, String deviceDescription) {
mDeviceName = deviceName;
mDeviceDescription = deviceDescription;
}
@@ -155,8 +282,8 @@
UsbAlsaDevice other = (UsbAlsaDevice) obj;
return (mCardNum == other.mCardNum
&& mDeviceNum == other.mDeviceNum
- && mHasPlayback == other.mHasPlayback
- && mHasCapture == other.mHasCapture
+ && mHasOutput == other.mHasOutput
+ && mHasInput == other.mHasInput
&& mIsInputHeadset == other.mIsInputHeadset
&& mIsOutputHeadset == other.mIsOutputHeadset);
}
@@ -170,8 +297,8 @@
int result = 1;
result = prime * result + mCardNum;
result = prime * result + mDeviceNum;
- result = prime * result + (mHasPlayback ? 0 : 1);
- result = prime * result + (mHasCapture ? 0 : 1);
+ result = prime * result + (mHasOutput ? 0 : 1);
+ result = prime * result + (mHasInput ? 0 : 1);
result = prime * result + (mIsInputHeadset ? 0 : 1);
result = prime * result + (mIsOutputHeadset ? 0 : 1);
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java b/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java
new file mode 100644
index 0000000..c498847
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+/**
+ * Detects and reports ALSA jack state and events.
+ */
+public final class UsbAlsaJackDetector implements Runnable {
+ private static final String TAG = "UsbAlsaJackDetector";
+
+ private static native boolean nativeHasJackDetect(int card);
+ private native boolean nativeJackDetect(int card);
+ private native boolean nativeOutputJackConnected(int card);
+ private native boolean nativeInputJackConnected(int card);
+
+ private boolean mStopJackDetect = false;
+ private UsbAlsaDevice mAlsaDevice;
+
+ /* use startJackDetect to create a UsbAlsaJackDetector */
+ private UsbAlsaJackDetector(UsbAlsaDevice device) {
+ mAlsaDevice = device;
+ }
+
+ /** If jack detection is detected on the given Alsa Device,
+ * create and return a UsbAlsaJackDetector which will update wired device state
+ * each time a jack detection event is registered.
+ *
+ * @returns UsbAlsaJackDetector if jack detect is supported, or null.
+ */
+ public static UsbAlsaJackDetector startJackDetect(UsbAlsaDevice device) {
+ if (!nativeHasJackDetect(device.getCardNum())) {
+ return null;
+ }
+ UsbAlsaJackDetector jackDetector = new UsbAlsaJackDetector(device);
+
+ // This thread will exit once the USB device disappears.
+ // It can also be convinced to stop with pleaseStop().
+ new Thread(jackDetector, "USB jack detect thread").start();
+ return jackDetector;
+ }
+
+ public boolean isInputJackConnected() {
+ return nativeInputJackConnected(mAlsaDevice.getCardNum());
+ }
+
+ public boolean isOutputJackConnected() {
+ return nativeOutputJackConnected(mAlsaDevice.getCardNum());
+ }
+
+ /**
+ * Stop the jack detect thread from calling back into UsbAlsaDevice.
+ * This doesn't force the thread to stop (which is deprecated in java and dangerous due to
+ * locking issues), but will cause the thread to exit at the next safe opportunity.
+ */
+ public void pleaseStop() {
+ synchronized (this) {
+ mStopJackDetect = true;
+ }
+ }
+
+ /**
+ * Called by nativeJackDetect each time a jack detect event is reported.
+ * @return false when the jackDetect thread should stop. true otherwise.
+ */
+ public boolean jackDetectCallback() {
+ synchronized (this) {
+ if (mStopJackDetect) {
+ return false;
+ }
+ mAlsaDevice.updateWiredDeviceConnectionState(true);
+ }
+ return true;
+ }
+
+ /**
+ * This will call jackDetectCallback each time it detects a jack detect event.
+ * If jackDetectCallback returns false, this function will return.
+ */
+ public void run() {
+ nativeJackDetect(mAlsaDevice.getCardNum());
+ }
+}
+
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 0c5f8f1..2f1c516 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -20,11 +20,9 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbDevice;
-import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.midi.MidiDeviceInfo;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.service.usb.UsbAlsaManagerProto;
@@ -32,7 +30,6 @@
import com.android.internal.alsa.AlsaCardsParser;
import com.android.internal.util.dump.DualDumpOutputStream;
-import com.android.server.audio.AudioService;
import com.android.server.usb.descriptors.UsbDescriptorParser;
import libcore.io.IoUtils;
@@ -58,6 +55,7 @@
// this is needed to map USB devices to ALSA Audio Devices, especially to remove an
// ALSA device when we are notified that its associated USB device has been removed.
private final ArrayList<UsbAlsaDevice> mAlsaDevices = new ArrayList<UsbAlsaDevice>();
+ private UsbAlsaDevice mSelectedDevice;
/**
* List of connected MIDI devices
@@ -78,17 +76,19 @@
ServiceManager.getService(Context.AUDIO_SERVICE));
}
- // Notifies AudioService when a device is added or removed
- // audioDevice - the AudioDevice that was added or removed
- // enabled - if true, we're connecting a device (it's arrived), else disconnecting
- private void notifyDeviceState(UsbAlsaDevice alsaDevice, boolean enabled) {
+ /**
+ * Select the AlsaDevice to be used for AudioService.
+ * AlsaDevice.start() notifies AudioService of it's connected state.
+ *
+ * @param alsaDevice The selected UsbAlsaDevice for system USB audio.
+ */
+ private synchronized void selectAlsaDevice(UsbAlsaDevice alsaDevice) {
if (DEBUG) {
- Slog.d(TAG, "notifyDeviceState " + enabled + " " + alsaDevice);
+ Slog.d(TAG, "selectAlsaDevice " + alsaDevice);
}
- if (mAudioService == null) {
- Slog.e(TAG, "no AudioService");
- return;
+ if (mSelectedDevice != null) {
+ deselectAlsaDevice();
}
// FIXME Does not yet handle the case where the setting is changed
@@ -102,40 +102,14 @@
return;
}
- int state = (enabled ? 1 : 0);
- int cardNum = alsaDevice.getCardNum();
- int deviceNum = alsaDevice.getDeviceNum();
- if (cardNum < 0 || deviceNum < 0) {
- Slog.e(TAG, "Invalid alsa card or device alsaCard: " + cardNum
- + " alsaDevice: " + deviceNum);
- return;
- }
+ mSelectedDevice = alsaDevice;
+ alsaDevice.start();
+ }
- String address = AudioService.makeAlsaAddressString(cardNum, deviceNum);
- try {
- // Playback Device
- if (alsaDevice.hasPlayback()) {
- int device = alsaDevice.isOutputHeadset()
- ? AudioSystem.DEVICE_OUT_USB_HEADSET
- : AudioSystem.DEVICE_OUT_USB_DEVICE;
- if (DEBUG) {
- Slog.i(TAG, "pre-call device:0x" + Integer.toHexString(device) +
- " addr:" + address + " name:" + alsaDevice.getDeviceName());
- }
- mAudioService.setWiredDeviceConnectionState(
- device, state, address, alsaDevice.getDeviceName(), TAG);
- }
-
- // Capture Device
- if (alsaDevice.hasCapture()) {
- int device = alsaDevice.isInputHeadset()
- ? AudioSystem.DEVICE_IN_USB_HEADSET
- : AudioSystem.DEVICE_IN_USB_DEVICE;
- mAudioService.setWiredDeviceConnectionState(
- device, state, address, alsaDevice.getDeviceName(), TAG);
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
+ private synchronized void deselectAlsaDevice() {
+ if (mSelectedDevice != null) {
+ mSelectedDevice.stop();
+ mSelectedDevice = null;
}
}
@@ -168,7 +142,7 @@
Slog.d(TAG, " alsaDevice:" + alsaDevice);
}
if (alsaDevice != null) {
- notifyDeviceState(alsaDevice, true /*enabled*/);
+ selectAlsaDevice(alsaDevice);
}
return alsaDevice;
} else {
@@ -202,16 +176,21 @@
if (hasInput || hasOutput) {
boolean isInputHeadset = parser.isInputHeadset();
boolean isOutputHeadset = parser.isOutputHeadset();
- UsbAlsaDevice alsaDevice =
- new UsbAlsaDevice(cardRec.getCardNum(), 0 /*device*/, deviceAddress,
- hasOutput, hasInput, isInputHeadset, isOutputHeadset);
- alsaDevice.setDeviceNameAndDescription(
- cardRec.getCardName(), cardRec.getCardDescription());
- mAlsaDevices.add(0, alsaDevice);
- // Select it
+ if (mAudioService == null) {
+ Slog.e(TAG, "no AudioService");
+ return;
+ }
+
+ UsbAlsaDevice alsaDevice =
+ new UsbAlsaDevice(mAudioService, cardRec.getCardNum(), 0 /*device*/,
+ deviceAddress, hasOutput, hasInput,
+ isInputHeadset, isOutputHeadset);
if (alsaDevice != null) {
- notifyDeviceState(alsaDevice, true /*enabled*/);
+ alsaDevice.setDeviceNameAndDescription(
+ cardRec.getCardName(), cardRec.getCardDescription());
+ mAlsaDevices.add(0, alsaDevice);
+ selectAlsaDevice(alsaDevice);
}
}
@@ -256,7 +235,7 @@
}
}
- /* package */ void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
+ /* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
if (DEBUG) {
Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")");
}
@@ -264,13 +243,9 @@
// Audio
UsbAlsaDevice alsaDevice = removeAlsaDeviceFromList(deviceAddress);
Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice);
- if (alsaDevice != null) {
- if (alsaDevice.hasPlayback() || alsaDevice.hasCapture()) {
- notifyDeviceState(alsaDevice, false /*enabled*/);
-
- // if there any external devices left, select one of them
- selectDefaultDevice();
- }
+ if (alsaDevice != null && alsaDevice == mSelectedDevice) {
+ deselectAlsaDevice();
+ selectDefaultDevice(); // if there any external devices left, select one of them
}
// MIDI