Merge "Add more light grey APIs." into pi-dev
diff --git a/Android.mk b/Android.mk
index 88394d6..bb37fa2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -448,6 +448,7 @@
-showAnnotation android.annotation.SystemApi \
-showAnnotation android.annotation.TestApi \
-privateDexApi $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+ -removedDexApi $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) \
-nodocs
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
@@ -456,7 +457,8 @@
include $(BUILD_DROIDDOC)
-$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+ $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
# ==== check javadoc comments but don't generate docs ========
include $(CLEAR_VARS)
@@ -871,9 +873,16 @@
# rules for building them. Other rules in the build system should depend on the
# files in the build folder.
-# Automatically add all methods which match the following signatures.
-# These need to be greylisted in order to allow applications to write their
-# own serializers.
+# Merge light greylist from multiple files:
+# (1) manual light greylist
+# (2) list of usages from vendor apps
+# (3) list of removed APIs
+# @removed does not imply private in Doclava. We must take the subset also
+# in PRIVATE_API.
+# (4) list of serialization APIs
+# Automatically adds all methods which match the signatures in
+# REGEX_SERIALIZATION. These are greylisted in order to allow applications
+# to write their own serializers.
$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): REGEX_SERIALIZATION := \
"readObject\(Ljava/io/ObjectInputStream;\)V" \
"readObjectNoData\(\)V" \
@@ -883,14 +892,15 @@
"writeObject\(Ljava/io/ObjectOutputStream;\)V" \
"writeReplace\(\)Ljava/lang/Object;"
$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
-# Temporarily merge light greylist from two files. Vendor list will become dark
-# grey once we remove the UI toast.
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): REMOVED_API := $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): frameworks/base/config/hiddenapi-light-greylist.txt \
frameworks/base/config/hiddenapi-vendor-list.txt \
- $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+ $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+ $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
sort frameworks/base/config/hiddenapi-light-greylist.txt \
frameworks/base/config/hiddenapi-vendor-list.txt \
<(grep -E "\->("$(subst $(space),"|",$(REGEX_SERIALIZATION))")$$" $(PRIVATE_API)) \
+ <(comm -12 <(sort $(REMOVED_API)) <(sort $(PRIVATE_API))) \
> $@
$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\
diff --git a/api/current.txt b/api/current.txt
index 26e4298..8703bf4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -162,6 +162,7 @@
public static final class Manifest.permission_group {
ctor public Manifest.permission_group();
field public static final java.lang.String CALENDAR = "android.permission-group.CALENDAR";
+ field public static final java.lang.String CALL_LOG = "android.permission-group.CALL_LOG";
field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
field public static final java.lang.String CONTACTS = "android.permission-group.CONTACTS";
field public static final java.lang.String LOCATION = "android.permission-group.LOCATION";
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 93875cd..e5bde0d 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -151,7 +151,8 @@
}
// ================================================================================
-Section::Section(int i, const int64_t timeoutMs) : id(i), timeoutMs(timeoutMs) {}
+Section::Section(int i, int64_t timeoutMs, bool deviceSpecific)
+ : id(i), timeoutMs(timeoutMs), deviceSpecific(deviceSpecific) {}
Section::~Section() {}
@@ -236,8 +237,9 @@
// ================================================================================
static inline bool isSysfs(const char* filename) { return strncmp(filename, "/sys/", 5) == 0; }
-FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs)
- : Section(id, timeoutMs), mFilename(filename) {
+FileSection::FileSection(int id, const char* filename, const bool deviceSpecific,
+ const int64_t timeoutMs)
+ : Section(id, timeoutMs, deviceSpecific), mFilename(filename) {
name = filename;
mIsSysfs = isSysfs(filename);
}
@@ -250,7 +252,7 @@
unique_fd fd(open(mFilename, O_RDONLY | O_CLOEXEC));
if (fd.get() == -1) {
ALOGW("FileSection '%s' failed to open file", this->name.string());
- return -errno;
+ return this->deviceSpecific ? NO_ERROR : -errno;
}
FdBuffer buffer;
@@ -902,11 +904,16 @@
// Read from the pipe concurrently to avoid blocking the child.
FdBuffer buffer;
err = buffer.readFully(dumpPipe.readFd().get());
+ // Wait on the child to avoid it becoming a zombie process.
+ status_t cStatus = wait_child(child);
if (err != NO_ERROR) {
ALOGW("TombstoneSection '%s' failed to read stack dump: %d", this->name.string(), err);
dumpPipe.readFd().reset();
break;
}
+ if (cStatus != NO_ERROR) {
+ ALOGE("TombstoneSection '%s' child had an issue: %s\n", this->name.string(), strerror(-cStatus));
+ }
auto dump = std::make_unique<char[]>(buffer.size());
auto iterator = buffer.data();
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 20ecdb1..577892e 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -40,9 +40,10 @@
public:
const int id;
const int64_t timeoutMs; // each section must have a timeout
+ const bool deviceSpecific;
String8 name;
- Section(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+ Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, bool deviceSpecific = false);
virtual ~Section();
virtual status_t Execute(ReportRequestSet* requests) const = 0;
@@ -75,7 +76,8 @@
*/
class FileSection : public Section {
public:
- FileSection(int id, const char* filename, const int64_t timeoutMs = 5000 /* 5 seconds */);
+ FileSection(int id, const char* filename, bool deviceSpecific = false,
+ int64_t timeoutMs = 5000 /* 5 seconds */);
virtual ~FileSection();
virtual status_t Execute(ReportRequestSet* requests) const;
@@ -105,7 +107,7 @@
*/
class WorkerThreadSection : public Section {
public:
- WorkerThreadSection(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+ WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
virtual ~WorkerThreadSection();
virtual status_t Execute(ReportRequestSet* requests) const;
@@ -118,7 +120,7 @@
*/
class CommandSection : public Section {
public:
- CommandSection(int id, const int64_t timeoutMs, const char* command, ...);
+ CommandSection(int id, int64_t timeoutMs, const char* command, ...);
CommandSection(int id, const char* command, ...);
@@ -168,7 +170,7 @@
*/
class TombstoneSection : public WorkerThreadSection {
public:
- TombstoneSection(int id, const char* type, const int64_t timeoutMs = 30000 /* 30 seconds */);
+ TombstoneSection(int id, const char* type, int64_t timeoutMs = 30000 /* 30 seconds */);
virtual ~TombstoneSection();
virtual status_t BlockingCall(int pipeWriteFd) const;
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 33f52062..3c338b3 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -143,8 +143,16 @@
EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\vatadtsetmai"));
}
+TEST_F(SectionTest, FileSectionNotExist) {
+ FileSection fs1(NOOP_PARSER, "notexist", false, QUICK_TIMEOUT_MS);
+ ASSERT_EQ(NAME_NOT_FOUND, fs1.Execute(&requests));
+
+ FileSection fs2(NOOP_PARSER, "notexist", true, QUICK_TIMEOUT_MS);
+ ASSERT_EQ(NO_ERROR, fs2.Execute(&requests));
+}
+
TEST_F(SectionTest, FileSectionTimeout) {
- FileSection fs(TIMEOUT_PARSER, tf.path, QUICK_TIMEOUT_MS);
+ FileSection fs(TIMEOUT_PARSER, tf.path, false, QUICK_TIMEOUT_MS);
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 5219885..763d49b 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "statslog.h"
@@ -162,6 +162,19 @@
OnLogEvent(event, false);
}
+void StatsLogProcessor::resetConfigs() {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
+ resetConfigsLocked(getElapsedRealtimeNs());
+}
+
+void StatsLogProcessor::resetConfigsLocked(const int64_t timestampNs) {
+ std::vector<ConfigKey> configKeys;
+ for (auto it = mMetricsManagers.begin(); it != mMetricsManagers.end(); it++) {
+ configKeys.push_back(it->first);
+ }
+ resetConfigsLocked(timestampNs, configKeys);
+}
+
void StatsLogProcessor::OnLogEvent(LogEvent* event, bool reconnected) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
const int64_t currentTimestampNs = event->GetElapsedTimestampNs();
@@ -188,11 +201,7 @@
WriteDataToDiskLocked(CONFIG_RESET);
// We see fresher event before we see the checkpoint. We might have lost data.
// The best we can do is to reset.
- std::vector<ConfigKey> configKeys;
- for (auto it = mMetricsManagers.begin(); it != mMetricsManagers.end(); it++) {
- configKeys.push_back(it->first);
- }
- resetConfigsLocked(currentTimestampNs, configKeys);
+ resetConfigsLocked(currentTimestampNs);
} else {
// Still in search of the CP. Keep going.
return;
@@ -242,6 +251,7 @@
void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key,
const StatsdConfig& config) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
+ WriteDataToDiskLocked(key, timestampNs, CONFIG_UPDATED);
OnConfigUpdatedLocked(timestampNs, key, config);
}
@@ -251,10 +261,6 @@
sp<MetricsManager> newMetricsManager =
new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
- auto it = mMetricsManagers.find(key);
- if (it != mMetricsManagers.end()) {
- WriteDataToDiskLocked(it->first, CONFIG_UPDATED);
- }
if (newMetricsManager->isConfigValid()) {
mUidMap->OnConfigUpdated(key);
if (newMetricsManager->shouldAddUidMapListener()) {
@@ -419,6 +425,7 @@
}
}
if (configKeysTtlExpired.size() > 0) {
+ WriteDataToDiskLocked(CONFIG_RESET);
resetConfigsLocked(timestampNs, configKeysTtlExpired);
}
}
@@ -427,7 +434,7 @@
std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
- WriteDataToDiskLocked(key, CONFIG_REMOVED);
+ WriteDataToDiskLocked(key, getElapsedRealtimeNs(), CONFIG_REMOVED);
mMetricsManagers.erase(it);
mUidMap->OnConfigRemoved(key);
}
@@ -474,9 +481,13 @@
}
void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key,
+ const int64_t timestampNs,
const DumpReportReason dumpReportReason) {
+ if (mMetricsManagers.find(key) == mMetricsManagers.end()) {
+ return;
+ }
ProtoOutputStream proto;
- onConfigMetricsReportLocked(key, getElapsedRealtimeNs(),
+ onConfigMetricsReportLocked(key, timestampNs,
true /* include_current_partial_bucket*/,
false /* include strings */, dumpReportReason, &proto);
string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
@@ -491,17 +502,19 @@
}
void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) {
+ const int64_t timeNs = getElapsedRealtimeNs();
for (auto& pair : mMetricsManagers) {
- WriteDataToDiskLocked(pair.first, dumpReportReason);
+ WriteDataToDiskLocked(pair.first, timeNs, dumpReportReason);
}
}
-void StatsLogProcessor::WriteDataToDisk(bool isShutdown) {
+void StatsLogProcessor::WriteDataToDisk(const DumpReportReason dumpReportReason) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- WriteDataToDiskLocked(DEVICE_SHUTDOWN);
+ WriteDataToDiskLocked(dumpReportReason);
}
void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
mStatsPullerManager.OnAlarmFired(timestampNs);
}
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index c3c4663..a6c4d86 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -77,7 +77,10 @@
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
/* Flushes data to disk. Data on memory will be gone after written to disk. */
- void WriteDataToDisk(bool shutdown);
+ void WriteDataToDisk(const DumpReportReason dumpReportReason);
+
+ // Reset all configs.
+ void resetConfigs();
inline sp<UidMap> getUidMap() {
return mUidMap;
@@ -121,8 +124,9 @@
void OnConfigUpdatedLocked(
const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
- void WriteDataToDiskLocked(DumpReportReason dumpReportReason);
- void WriteDataToDiskLocked(const ConfigKey& key, DumpReportReason dumpReportReason);
+ void WriteDataToDiskLocked(const DumpReportReason dumpReportReason);
+ void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs,
+ const DumpReportReason dumpReportReason);
void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
const bool include_current_partial_bucket,
@@ -141,6 +145,9 @@
// Handler over the isolated uid change event.
void onIsolatedUidChangedEventLocked(const LogEvent& event);
+ // Reset all configs.
+ void resetConfigsLocked(const int64_t timestampNs);
+ // Reset the specified configs.
void resetConfigsLocked(const int64_t timestampNs, const std::vector<ConfigKey>& configs);
// Function used to send a broadcast so that receiver for the config key can call getData
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 0e7b4f9..811edb5 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -659,7 +659,7 @@
status_t StatsService::cmd_write_data_to_disk(FILE* out) {
fprintf(out, "Writing data to disk\n");
- mProcessor->WriteDataToDisk(false);
+ mProcessor->WriteDataToDisk(ADB_DUMP);
return NO_ERROR;
}
@@ -816,10 +816,10 @@
return Status::ok();
}
-Status StatsService::informDeviceShutdown(bool isShutdown) {
+Status StatsService::informDeviceShutdown() {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informDeviceShutdown");
- mProcessor->WriteDataToDisk(isShutdown);
+ mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN);
return Status::ok();
}
@@ -967,7 +967,12 @@
void StatsService::binderDied(const wp <IBinder>& who) {
ALOGW("statscompanion service died");
- mProcessor->WriteDataToDisk(STATSCOMPANION_DIED);
+ StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
+ if (mProcessor != nullptr) {
+ ALOGW("Reset statsd upon system server restars.");
+ mProcessor->WriteDataToDisk(STATSCOMPANION_DIED);
+ mProcessor->resetConfigs();
+ }
mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
SubscriberReporter::getInstance().setStatsCompanionService(nullptr);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index e409a71..af4cbff 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -66,7 +66,7 @@
const vector<String16>& app);
virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version);
virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
- virtual Status informDeviceShutdown(bool isShutdown);
+ virtual Status informDeviceShutdown();
/**
* Called right before we start processing events.
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp
index c8e406f..8d73699 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.cpp
+++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "anomaly/AlarmTracker.h"
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index 3f69a2c..ee9e9c0 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include <android/os/IIncidentManager.h>
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index ee3ed23..764366f 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -51,6 +51,7 @@
const int FIELD_ID_LOGGER_ERROR_STATS = 11;
const int FIELD_ID_PERIODIC_ALARM_STATS = 12;
const int FIELD_ID_LOG_LOSS_STATS = 14;
+const int FIELD_ID_SYSTEM_SERVER_RESTART = 15;
const int FIELD_ID_ATOM_STATS_TAG = 1;
const int FIELD_ID_ATOM_STATS_COUNT = 2;
@@ -355,6 +356,15 @@
mPushedAtomStats[atomId]++;
}
+void StatsdStats::noteSystemServerRestart(int32_t timeSec) {
+ lock_guard<std::mutex> lock(mLock);
+
+ if (mSystemServerRestartSec.size() == kMaxSystemServerRestarts) {
+ mSystemServerRestartSec.pop_front();
+ }
+ mSystemServerRestartSec.push_back(timeSec);
+}
+
void StatsdStats::noteLoggerError(int error) {
lock_guard<std::mutex> lock(mLock);
// grows strictly one at a time. so it won't > kMaxLoggerErrors
@@ -377,6 +387,7 @@
mAnomalyAlarmRegisteredStats = 0;
mPeriodicAlarmRegisteredStats = 0;
mLoggerErrors.clear();
+ mSystemServerRestartSec.clear();
mLogLossTimestampNs.clear();
for (auto& config : mConfigStats) {
config.second->broadcast_sent_time_sec.clear();
@@ -395,7 +406,7 @@
time_t t = timeSec;
struct tm* tm = localtime(&t);
char timeBuffer[80];
- strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
+ strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p", tm);
return string(timeBuffer);
}
@@ -511,6 +522,12 @@
strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M%p\n", error_tm);
fprintf(out, "Logger error %d at %s\n", error.second, buffer);
}
+
+ for (const auto& restart : mSystemServerRestartSec) {
+ fprintf(out, "System server restarts at %s(%lld)\n",
+ buildTimeString(restart).c_str(), (long long)restart);
+ }
+
for (const auto& loss : mLogLossTimestampNs) {
fprintf(out, "Log loss detected at %lld (elapsedRealtimeNs)\n", (long long)loss);
}
@@ -673,6 +690,11 @@
(long long)loss);
}
+ for (const auto& restart : mSystemServerRestartSec) {
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_SYSTEM_SERVER_RESTART | FIELD_COUNT_REPEATED,
+ restart);
+ }
+
output->clear();
size_t bufferSize = proto.size();
output->resize(bufferSize);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 65ba4f7..74541d3 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -104,6 +104,8 @@
const static int kMaxLoggerErrors = 20;
+ const static int kMaxSystemServerRestarts = 20;
+
const static int kMaxTimestampCount = 20;
const static int kMaxLogSourceCount = 50;
@@ -275,6 +277,11 @@
*/
void noteLoggerError(int error);
+ /*
+ * Records when system server restarts.
+ */
+ void noteSystemServerRestart(int32_t timeSec);
+
/**
* Records statsd skipped an event.
*/
@@ -338,6 +345,8 @@
// Timestamps when we detect log loss after logd reconnect.
std::list<int64_t> mLogLossTimestampNs;
+ std::list<int32_t> mSystemServerRestartSec;
+
// Stores the number of times statsd modified the anomaly alarm registered with
// StatsCompanionService.
int mAnomalyAlarmRegisteredStats = 0;
@@ -366,6 +375,7 @@
FRIEND_TEST(StatsdStatsTest, TestAtomLog);
FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold);
FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor);
+ FRIEND_TEST(StatsdStatsTest, TestSystemServerCrash);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 5ff8082..df08181 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "MetricProducer.h"
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 9ca4daa..bf0f720 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "MetricsManager.h"
#include "statslog.h"
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 9236864..2fe17da 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -383,4 +383,6 @@
repeated SkippedLogEventStats skipped_log_event_stats = 13;
repeated int64 log_loss_stats = 14;
+
+ repeated int32 system_restart_sec = 15;
}
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 1c18f67..6e4b2c8 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define DEBUG true
+#define DEBUG false
#include "Log.h"
#include "IncidentdReporter.h"
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index e99e402..967ef3c 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -298,6 +298,28 @@
EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
}
+TEST(StatsdStatsTest, TestSystemServerCrash) {
+ StatsdStats stats;
+ vector<int32_t> timestamps;
+ for (int i = 0; i < StatsdStats::kMaxSystemServerRestarts; i++) {
+ timestamps.push_back(i);
+ stats.noteSystemServerRestart(timestamps[i]);
+ }
+ vector<uint8_t> output;
+ stats.dumpStats(&output, false);
+ StatsdStatsReport report;
+ EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
+ const int maxCount = StatsdStats::kMaxSystemServerRestarts;
+ EXPECT_EQ(maxCount, (int)report.system_restart_sec_size());
+
+ stats.noteSystemServerRestart(StatsdStats::kMaxSystemServerRestarts + 1);
+ output.clear();
+ stats.dumpStats(&output, false);
+ EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
+ EXPECT_EQ(maxCount, (int)report.system_restart_sec_size());
+ EXPECT_EQ(StatsdStats::kMaxSystemServerRestarts + 1, report.system_restart_sec(maxCount - 1));
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index dc48a47..e552ce9 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -212,6 +212,7 @@
Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
Landroid/app/ApplicationPackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
Landroid/app/AppOpsManager$OpEntry;->getDuration()I
+Landroid/app/AppOpsManager$OpEntry;->getMode()I
Landroid/app/AppOpsManager$OpEntry;->getRejectTime()J
Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
@@ -287,6 +288,7 @@
Landroid/app/DownloadManager;->setAccessFilename(Z)V
Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
Landroid/app/Fragment;->mWho:Ljava/lang/String;
+Landroid/app/FragmentManagerImpl;->loadAnimator(Landroid/app/Fragment;IZI)Landroid/animation/Animator;
Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
Landroid/app/FragmentManagerImpl;->mStateSaved:Z
Landroid/app/FragmentManagerImpl;->noteStateNotSaved()V
@@ -304,6 +306,7 @@
Landroid/app/IActivityManager;->getConfiguration()Landroid/content/res/Configuration;
Landroid/app/IActivityManager;->getIntentSender(ILjava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I[Landroid/content/Intent;[Ljava/lang/String;ILandroid/os/Bundle;I)Landroid/content/IIntentSender;
Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String;
+Landroid/app/IActivityManager;->getPackageProcessState(Ljava/lang/String;Ljava/lang/String;)I
Landroid/app/IActivityManager;->getProviderMimeType(Landroid/net/Uri;I)Ljava/lang/String;
Landroid/app/IActivityManager;->getTaskForActivity(Landroid/os/IBinder;Z)I
Landroid/app/IActivityManager;->moveActivityTaskToBack(Landroid/os/IBinder;Z)Z
@@ -412,14 +415,12 @@
Landroid/app/Notification$Action;->mIcon:Landroid/graphics/drawable/Icon;
Landroid/app/Notification$Builder;->mActions:Ljava/util/ArrayList;
Landroid/app/Notification$Builder;->makePublicContentView()Landroid/widget/RemoteViews;
-Landroid/app/Notification$Builder;->setChannel(Ljava/lang/String;)Landroid/app/Notification$Builder;
Landroid/app/Notification;-><init>(Landroid/content/Context;ILjava/lang/CharSequence;JLjava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/content/Intent;)V
Landroid/app/Notification;->isGroupSummary()Z
Landroid/app/Notification;->mChannelId:Ljava/lang/String;
Landroid/app/Notification;->mGroupKey:Ljava/lang/String;
Landroid/app/Notification;->mLargeIcon:Landroid/graphics/drawable/Icon;
Landroid/app/Notification;->mSmallIcon:Landroid/graphics/drawable/Icon;
-Landroid/app/Notification;->setLatestEventInfo(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/app/PendingIntent;)V
Landroid/app/Notification;->setSmallIcon(Landroid/graphics/drawable/Icon;)V
Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager;
Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V
@@ -452,11 +453,6 @@
Landroid/app/SharedPreferencesImpl;-><init>(Ljava/io/File;I)V
Landroid/app/SharedPreferencesImpl;->mFile:Ljava/io/File;
Landroid/app/SharedPreferencesImpl;->startReloadIfChangedUnexpectedly()V
-Landroid/app/slice/Slice$Builder;-><init>(Landroid/net/Uri;)V
-Landroid/app/slice/Slice$Builder;->setSpec(Landroid/app/slice/SliceSpec;)Landroid/app/slice/Slice$Builder;
-Landroid/app/slice/SliceItem;->getTimestamp()J
-Landroid/app/slice/SliceManager;->bindSlice(Landroid/net/Uri;Ljava/util/List;)Landroid/app/slice/Slice;
-Landroid/app/slice/SliceManager;->pinSlice(Landroid/net/Uri;Ljava/util/List;)V
Landroid/app/StatusBarManager;->collapsePanels()V
Landroid/app/StatusBarManager;->disable(I)V
Landroid/app/StatusBarManager;->expandNotificationsPanel()V
@@ -704,9 +700,11 @@
Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
+Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/content/pm/IPackageDeleteObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver2;
Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -775,6 +773,7 @@
Landroid/content/pm/PackageInstaller$SessionParams;->sizeBytes:J
Landroid/content/pm/PackageItemInfo;->setForceSafeLabels(Z)V
Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
+Landroid/content/pm/PackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V
Landroid/content/pm/PackageManager;->freeStorage(JLandroid/content/IntentSender;)V
Landroid/content/pm/PackageManager;->freeStorage(Ljava/lang/String;JLandroid/content/IntentSender;)V
Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
@@ -847,11 +846,11 @@
Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package;
Landroid/content/pm/PackageUserState;-><init>()V
Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
-Landroid/content/pm/ResolveInfo;->instantAppAvailable:Z
Landroid/content/pm/ShortcutManager;->mService:Landroid/content/pm/IShortcutService;
Landroid/content/pm/Signature;->getPublicKey()Ljava/security/PublicKey;
Landroid/content/pm/UserInfo;-><init>(ILjava/lang/String;I)V
Landroid/content/pm/UserInfo;->FLAG_PRIMARY:I
+Landroid/content/pm/UserInfo;->getUserHandle()Landroid/os/UserHandle;
Landroid/content/pm/UserInfo;->id:I
Landroid/content/pm/UserInfo;->isPrimary()Z
Landroid/content/pm/UserInfo;->serialNumber:I
@@ -969,8 +968,8 @@
Landroid/content/UriMatcher;->mText:Ljava/lang/String;
Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
-Landroid/database/AbstractCursor;->mRowIdColumnIndex:I
Landroid/database/AbstractWindowedCursor;->clearOrCreateWindow(Ljava/lang/String;)V
+Landroid/database/AbstractWindowedCursor;->closeWindow()V
Landroid/database/CursorWindow;->mWindowPtr:J
Landroid/database/CursorWindow;->sCursorWindowSize:I
Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
@@ -979,6 +978,7 @@
Landroid/database/sqlite/SQLiteCustomFunction;->name:Ljava/lang/String;
Landroid/database/sqlite/SQLiteCustomFunction;->numArgs:I
Landroid/database/sqlite/SQLiteDatabase;->CONFLICT_VALUES:[Ljava/lang/String;
+Landroid/database/sqlite/SQLiteDatabase;->getThreadSession()Landroid/database/sqlite/SQLiteSession;
Landroid/database/sqlite/SQLiteDatabase;->mConfigurationLocked:Landroid/database/sqlite/SQLiteDatabaseConfiguration;
Landroid/database/sqlite/SQLiteDatabase;->mConnectionPoolLocked:Landroid/database/sqlite/SQLiteConnectionPool;
Landroid/database/sqlite/SQLiteDatabase;->reopenReadWrite()V
@@ -987,11 +987,10 @@
Landroid/database/sqlite/SQLiteDebug$PagerStats;->memoryUsed:I
Landroid/database/sqlite/SQLiteDebug$PagerStats;->pageCacheOverflow:I
Landroid/database/sqlite/SQLiteOpenHelper;->mName:Ljava/lang/String;
+Landroid/database/sqlite/SQLiteSession;->beginTransaction(ILandroid/database/sqlite/SQLiteTransactionListener;ILandroid/os/CancellationSignal;)V
Landroid/database/sqlite/SQLiteStatement;-><init>(Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;[Ljava/lang/Object;)V
Landroid/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
Landroid/ddm/DdmHandleAppName;->setAppName(Ljava/lang/String;I)V
-Landroid/graphics/AvoidXfermode$Mode;->AVOID:Landroid/graphics/AvoidXfermode$Mode;
-Landroid/graphics/AvoidXfermode$Mode;->TARGET:Landroid/graphics/AvoidXfermode$Mode;
Landroid/graphics/BaseCanvas;->mNativeCanvasWrapper:J
Landroid/graphics/Bitmap$Config;->nativeInt:I
Landroid/graphics/Bitmap$Config;->nativeToConfig(I)Landroid/graphics/Bitmap$Config;
@@ -1012,7 +1011,6 @@
Landroid/graphics/Camera;->native_instance:J
Landroid/graphics/Canvas;-><init>(J)V
Landroid/graphics/Canvas;->release()V
-Landroid/graphics/Canvas;->save(I)I
Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mStateIds:Landroid/util/SparseIntArray;
@@ -1057,6 +1055,7 @@
Landroid/graphics/drawable/GradientDrawable;->getOpticalInsets()Landroid/graphics/Insets;
Landroid/graphics/drawable/GradientDrawable;->mGradientState:Landroid/graphics/drawable/GradientDrawable$GradientState;
Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
+Landroid/graphics/drawable/Icon;->createWithResource(Landroid/content/res/Resources;I)Landroid/graphics/drawable/Icon;
Landroid/graphics/drawable/Icon;->getBitmap()Landroid/graphics/Bitmap;
Landroid/graphics/drawable/Icon;->getDataBytes()[B
Landroid/graphics/drawable/Icon;->getDataLength()I
@@ -1107,7 +1106,6 @@
Landroid/graphics/NinePatch$InsetStruct;-><init>(IIIIIIIIFIF)V
Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap;
Landroid/graphics/Picture;->mNativePicture:J
-Landroid/graphics/PixelXorXfermode;-><init>(I)V
Landroid/graphics/PorterDuffColorFilter;->getColor()I
Landroid/graphics/PorterDuffColorFilter;->setColor(I)V
Landroid/graphics/PorterDuffColorFilter;->setMode(Landroid/graphics/PorterDuff$Mode;)V
@@ -1204,6 +1202,7 @@
Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay;
Landroid/hardware/fingerprint/Fingerprint;->getFingerId()I
Landroid/hardware/fingerprint/Fingerprint;->getName()Ljava/lang/CharSequence;
+Landroid/hardware/fingerprint/FingerprintManager;->getEnrolledFingerprints()Ljava/util/List;
Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/hardware/HardwareBuffer;-><init>(J)V
Landroid/hardware/HardwareBuffer;->mNativeObject:J
@@ -1240,6 +1239,7 @@
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->data:[B
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->captureSession:I
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->data:[B
Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B
Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->uuid:Ljava/util/UUID;
@@ -1515,7 +1515,6 @@
Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z
Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager;
Landroid/net/ConnectivityManager;->registerNetworkFactory(Landroid/os/Messenger;Ljava/lang/String;)V
-Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z
Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z
Landroid/net/ConnectivityManager;->setBackgroundDataSetting(Z)V
Landroid/net/ConnectivityManager;->TYPE_MOBILE_CBS:I
@@ -1575,7 +1574,6 @@
Landroid/net/SSLCertificateSocketFactory;->castToOpenSSLSocket(Ljava/net/Socket;)Lcom/android/org/conscrypt/OpenSSLSocketImpl;
Landroid/net/SSLCertificateSocketFactory;->getAlpnSelectedProtocol(Ljava/net/Socket;)[B
Landroid/net/SSLCertificateSocketFactory;->getDelegate()Ljavax/net/ssl/SSLSocketFactory;
-Landroid/net/SSLCertificateSocketFactory;->getHttpSocketFactory(ILandroid/net/SSLSessionCache;)Lorg/apache/http/conn/ssl/SSLSocketFactory;
Landroid/net/SSLCertificateSocketFactory;->INSECURE_TRUST_MANAGER:[Ljavax/net/ssl/TrustManager;
Landroid/net/SSLCertificateSocketFactory;->isSslCheckRelaxed()Z
Landroid/net/SSLCertificateSocketFactory;->makeSocketFactory([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;)Ljavax/net/ssl/SSLSocketFactory;
@@ -1643,7 +1641,6 @@
Landroid/net/wifi/ScanResult;->informationElements:[Landroid/net/wifi/ScanResult$InformationElement;
Landroid/net/wifi/ScanResult;->numUsage:I
Landroid/net/wifi/ScanResult;->seen:J
-Landroid/net/wifi/ScanResult;->untrusted:Z
Landroid/net/wifi/ScanResult;->wifiSsid:Landroid/net/wifi/WifiSsid;
Landroid/net/wifi/WifiConfiguration;->apBand:I
Landroid/net/wifi/WifiConfiguration;->apChannel:I
@@ -1790,6 +1787,7 @@
Landroid/os/HwParcel;-><init>(Z)V
Landroid/os/HwRemoteBinder;-><init>()V
Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/os/IDeviceIdleController;->getAppIdTempWhitelist()[I
Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z
Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController;
Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1837,9 +1835,7 @@
Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
-Landroid/os/PowerManager;->userActivity(JZ)V
Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
-Landroid/os/PowerManager;->wakeUp(J)V
Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V
Landroid/os/Process;->getFreeMemory()J
Landroid/os/Process;->getParentPid(I)I
@@ -1847,6 +1843,7 @@
Landroid/os/Process;->getTotalMemory()J
Landroid/os/Process;->getUidForPid(I)I
Landroid/os/Process;->isIsolated(I)Z
+Landroid/os/Process;->parseProcLine([BII[I[Ljava/lang/String;[J[F)Z
Landroid/os/Process;->readProcFile(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z
Landroid/os/Process;->readProcLines(Ljava/lang/String;[Ljava/lang/String;[J)V
Landroid/os/Process;->setArgV0(Ljava/lang/String;)V
@@ -1873,11 +1870,9 @@
Landroid/os/storage/StorageManager;->findVolumeByUuid(Ljava/lang/String;)Landroid/os/storage/VolumeInfo;
Landroid/os/storage/StorageManager;->getBestVolumeDescription(Landroid/os/storage/VolumeInfo;)Ljava/lang/String;
Landroid/os/storage/StorageManager;->getDisks()Ljava/util/List;
-Landroid/os/storage/StorageManager;->getPrimaryVolume()Landroid/os/storage/StorageVolume;
Landroid/os/storage/StorageManager;->getStorageBytesUntilLow(Ljava/io/File;)J
Landroid/os/storage/StorageManager;->getStorageFullBytes(Ljava/io/File;)J
Landroid/os/storage/StorageManager;->getStorageLowBytes(Ljava/io/File;)J
-Landroid/os/storage/StorageManager;->getVolumeList()[Landroid/os/storage/StorageVolume;
Landroid/os/storage/StorageManager;->getVolumeList(II)[Landroid/os/storage/StorageVolume;
Landroid/os/storage/StorageManager;->getVolumePaths()[Ljava/lang/String;
Landroid/os/storage/StorageManager;->getVolumes()Ljava/util/List;
@@ -1888,6 +1883,7 @@
Landroid/os/storage/StorageVolume;->getPathFile()Ljava/io/File;
Landroid/os/storage/StorageVolume;->getUserLabel()Ljava/lang/String;
Landroid/os/storage/StorageVolume;->mPath:Ljava/io/File;
+Landroid/os/storage/StorageVolume;->mRemovable:Z
Landroid/os/storage/VolumeInfo;->buildStorageVolume(Landroid/content/Context;IZ)Landroid/os/storage/StorageVolume;
Landroid/os/storage/VolumeInfo;->getDisk()Landroid/os/storage/DiskInfo;
Landroid/os/storage/VolumeInfo;->getEnvironmentForState(I)Ljava/lang/String;
@@ -1900,12 +1896,12 @@
Landroid/os/storage/VolumeInfo;->TYPE_EMULATED:I
Landroid/os/storage/VolumeInfo;->TYPE_PUBLIC:I
Landroid/os/StrictMode$Span;->finish()V
-Landroid/os/StrictMode$ThreadPolicy$Builder;->penaltyListener(Landroid/os/StrictMode$OnThreadViolationListener;Ljava/util/concurrent/Executor;)Landroid/os/StrictMode$ThreadPolicy$Builder;
Landroid/os/StrictMode;->conditionallyCheckInstanceCounts()V
Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
Landroid/os/StrictMode;->enterCriticalSpan(Ljava/lang/String;)Landroid/os/StrictMode$Span;
Landroid/os/StrictMode;->getThreadPolicyMask()I
Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
+Landroid/os/StrictMode;->sLastVmViolationTime:Ljava/util/HashMap;
Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
Landroid/os/SystemProperties;-><init>()V
Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V
@@ -1952,7 +1948,6 @@
Landroid/os/UserHandle;->USER_SERIAL_SYSTEM:I
Landroid/os/UserHandle;->USER_SYSTEM:I
Landroid/os/UserManager;->get(Landroid/content/Context;)Landroid/os/UserManager;
-Landroid/os/UserManager;->getBadgedLabelForUser(Ljava/lang/CharSequence;Landroid/os/UserHandle;)Ljava/lang/CharSequence;
Landroid/os/UserManager;->getMaxSupportedUsers()I
Landroid/os/UserManager;->getProfiles(I)Ljava/util/List;
Landroid/os/UserManager;->getUserHandle()I
@@ -2027,17 +2022,8 @@
Landroid/print/PrinterId;->getServiceName()Landroid/content/ComponentName;
Landroid/print/PrintJobInfo;->getAdvancedOptions()Landroid/os/Bundle;
Landroid/print/PrintJobInfo;->getDocumentInfo()Landroid/print/PrintDocumentInfo;
-Landroid/provider/Browser$BookmarkColumns;->DATE:Ljava/lang/String;
-Landroid/provider/Browser;->BOOKMARKS_URI:Landroid/net/Uri;
-Landroid/provider/Browser;->canClearHistory(Landroid/content/ContentResolver;)Z
-Landroid/provider/Browser;->clearHistory(Landroid/content/ContentResolver;)V
-Landroid/provider/Browser;->clearSearches(Landroid/content/ContentResolver;)V
-Landroid/provider/Browser;->deleteFromHistory(Landroid/content/ContentResolver;Ljava/lang/String;)V
Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String;
-Landroid/provider/Browser;->HISTORY_PROJECTION:[Ljava/lang/String;
-Landroid/provider/Browser;->SEARCHES_URI:Landroid/net/Uri;
Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/provider/Browser;->updateVisitedHistory(Landroid/content/ContentResolver;Ljava/lang/String;Z)V
Landroid/provider/CalendarContract$CalendarAlerts;->findNextAlarmTime(Landroid/content/ContentResolver;J)J
Landroid/provider/CalendarContract$CalendarAlerts;->rescheduleMissedAlarms(Landroid/content/ContentResolver;Landroid/content/Context;Landroid/app/AlarmManager;)V
Landroid/provider/Downloads$Impl$RequestHeaders;->INSERT_KEY_PREFIX:Ljava/lang/String;
@@ -2083,7 +2069,6 @@
Landroid/provider/Settings$System;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
Landroid/provider/Settings$System;->SCREEN_AUTO_BRIGHTNESS_ADJ:Ljava/lang/String;
Landroid/provider/Settings$System;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$System;->VOLUME_SETTINGS:[Ljava/lang/String;
Landroid/provider/Settings;->isCallingPackageAllowedToDrawOverlays(Landroid/content/Context;ILjava/lang/String;Z)Z
Landroid/provider/Settings;->isCallingPackageAllowedToWriteSettings(Landroid/content/Context;ILjava/lang/String;Z)Z
Landroid/provider/Telephony$Sms$Inbox;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Z)Landroid/net/Uri;
@@ -2292,8 +2277,6 @@
Landroid/renderscript/RenderScriptCacheDir;->mCacheDir:Ljava/io/File;
Landroid/renderscript/RenderScriptCacheDir;->setupDiskCache(Ljava/io/File;)V
Landroid/security/keystore/AndroidKeyStoreProvider;->getKeyStoreOperationHandle(Ljava/lang/Object;)J
-Landroid/security/keystore/recovery/RecoveryController;->getRecoveryStatus(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/security/keystore/recovery/RecoveryController;->initRecoveryService(Ljava/lang/String;[B)V
Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore;
Landroid/security/net/config/RootTrustManager;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
@@ -2305,8 +2288,6 @@
Landroid/service/media/MediaBrowserService;->KEY_MEDIA_ITEM:Ljava/lang/String;
Landroid/service/notification/NotificationListenerService;->isBound()Z
Landroid/service/notification/NotificationListenerService;->mHandler:Landroid/os/Handler;
-Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V
-Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V
Landroid/service/notification/StatusBarNotification;->getInitialPid()I
Landroid/service/notification/StatusBarNotification;->getUid()I
Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
@@ -2375,6 +2356,9 @@
Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String;
Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
Landroid/telecom/TelecomManager;->setUserSelectedOutgoingPhoneAccount(Landroid/telecom/PhoneAccountHandle;)V
+Landroid/telephony/CellIdentityGsm;->mBsic:I
+Landroid/telephony/CellSignalStrengthGsm;->mBitErrorRate:I
+Landroid/telephony/CellSignalStrengthGsm;->mSignalStrength:I
Landroid/telephony/CellSignalStrengthLte;->mCqi:I
Landroid/telephony/CellSignalStrengthLte;->mRsrp:I
Landroid/telephony/CellSignalStrengthLte;->mRsrq:I
@@ -2409,6 +2393,8 @@
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
+Landroid/telephony/SmsManager;->deleteMessageFromIcc(I)Z
+Landroid/telephony/SmsManager;->getAllMessagesFromIcc()Ljava/util/ArrayList;
Landroid/telephony/SmsManager;->sendMultipartTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;IZI)V
Landroid/telephony/SmsManager;->sendTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
Landroid/telephony/SmsMessage;->getSubId()I
@@ -2435,6 +2421,7 @@
Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getMultiSimConfiguration()Landroid/telephony/TelephonyManager$MultiSimVariants;
+Landroid/telephony/TelephonyManager;->getNai(I)Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getNetworkClass(I)I
Landroid/telephony/TelephonyManager;->getNetworkCountryIso(I)Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getNetworkOperator(I)Ljava/lang/String;
@@ -2662,6 +2649,7 @@
Landroid/view/IWindowManager;->getAnimationScale(I)F
Landroid/view/IWindowManager;->hasNavigationBar()Z
Landroid/view/IWindowManager;->setAnimationScale(IF)V
+Landroid/view/IWindowManager;->setAnimationScales([F)V
Landroid/view/IWindowManager;->setShelfHeight(ZI)V
Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
@@ -2810,7 +2798,6 @@
Landroid/view/View;->getViewRootImpl()Landroid/view/ViewRootImpl;
Landroid/view/View;->getWindowDisplayFrame(Landroid/graphics/Rect;)V
Landroid/view/View;->includeForAccessibility()Z
-Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V
Landroid/view/View;->internalSetPadding(IIII)V
Landroid/view/View;->invalidateParentIfNeeded()V
Landroid/view/View;->isPaddingResolved()Z
@@ -2878,7 +2865,6 @@
Landroid/view/View;->transformMatrixToLocal(Landroid/graphics/Matrix;)V
Landroid/view/ViewConfiguration;->getDeviceGlobalActionKeyTimeout()J
Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
-Landroid/view/ViewConfiguration;->getScaledScrollFactor()I
Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z
Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z
Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z
@@ -2919,6 +2905,7 @@
Landroid/view/ViewTreeObserver$InternalInsetsInfo;->TOUCHABLE_INSETS_REGION:I
Landroid/view/ViewTreeObserver;->addOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
Landroid/view/ViewTreeObserver;->removeOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
+Landroid/view/Window;->addPrivateFlags(I)V
Landroid/view/Window;->mAppName:Ljava/lang/String;
Landroid/view/Window;->mAppToken:Landroid/os/IBinder;
Landroid/view/Window;->mCallback:Landroid/view/Window$Callback;
@@ -2970,6 +2957,7 @@
Landroid/webkit/CacheManager;->saveCacheFile(Ljava/lang/String;Landroid/webkit/CacheManager$CacheResult;)V
Landroid/webkit/CacheManager;->startCacheTransaction()Z
Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/webkit/IWebViewUpdateService$Stub$Proxy;->waitForAndGetProvider()Landroid/webkit/WebViewProviderResponse;
Landroid/webkit/WebResourceResponse;->mImmutable:Z
Landroid/webkit/WebSettings$TextSize;->value:I
Landroid/webkit/WebSyncManager;->mHandler:Landroid/os/Handler;
@@ -2988,7 +2976,6 @@
Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z
Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z
Landroid/webkit/WebView;->sEnforceThreadChecking:Z
-Landroid/webkit/WebViewClient;->onUnhandledInputEvent(Landroid/webkit/WebView;Landroid/view/InputEvent;)V
Landroid/webkit/WebViewDelegate;-><init>()V
Landroid/webkit/WebViewFactory;->getProvider()Landroid/webkit/WebViewFactoryProvider;
Landroid/webkit/WebViewFactory;->getUpdateService()Landroid/webkit/IWebViewUpdateService;
@@ -3111,8 +3098,6 @@
Landroid/widget/ListView;->fillDown(II)Landroid/view/View;
Landroid/widget/ListView;->fillSpecific(II)Landroid/view/View;
Landroid/widget/ListView;->fillUp(II)Landroid/view/View;
-Landroid/widget/ListView;->findViewTraversal(I)Landroid/view/View;
-Landroid/widget/ListView;->findViewWithTagTraversal(Ljava/lang/Object;)Landroid/view/View;
Landroid/widget/ListView;->mAreAllItemsSelectable:Z
Landroid/widget/ListView;->mFooterViewInfos:Ljava/util/ArrayList;
Landroid/widget/ListView;->mHeaderViewInfos:Ljava/util/ArrayList;
@@ -3121,7 +3106,9 @@
Landroid/widget/MediaController;->mDecor:Landroid/view/View;
Landroid/widget/MediaController;->mDecorLayoutParams:Landroid/view/WindowManager$LayoutParams;
Landroid/widget/MediaController;->mWindowManager:Landroid/view/WindowManager;
+Landroid/widget/NumberPicker;->initializeSelectorWheelIndices()V
Landroid/widget/NumberPicker;->mInputText:Landroid/widget/EditText;
+Landroid/widget/NumberPicker;->mMaxValue:I
Landroid/widget/NumberPicker;->mSelectionDivider:Landroid/graphics/drawable/Drawable;
Landroid/widget/NumberPicker;->mSelectionDividerHeight:I
Landroid/widget/NumberPicker;->mSelectorWheelPaint:Landroid/graphics/Paint;
@@ -3219,7 +3206,6 @@
Landroid/widget/TextView;->assumeLayout()V
Landroid/widget/TextView;->createEditorIfNeeded()V
Landroid/widget/TextView;->getHorizontallyScrolling()Z
-Landroid/widget/TextView;->getTextColor(Landroid/content/Context;Landroid/content/res/TypedArray;I)I
Landroid/widget/TextView;->isSingleLine()Z
Landroid/widget/TextView;->LINES:I
Landroid/widget/TextView;->mCursorDrawableRes:I
@@ -3232,6 +3218,7 @@
Landroid/widget/TextView;->mSingleLine:Z
Landroid/widget/TextView;->mText:Ljava/lang/CharSequence;
Landroid/widget/TextView;->mTextPaint:Landroid/text/TextPaint;
+Landroid/widget/TextView;->mTextSelectHandleLeftRes:I
Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;Landroid/widget/TextView$BufferType;ZI)V
Landroid/widget/Toast$TN;->mNextView:Landroid/view/View;
Landroid/widget/Toast$TN;->mParams:Landroid/view/WindowManager$LayoutParams;
@@ -3337,9 +3324,13 @@
Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
+Lcom/android/internal/content/PackageMonitor;->onPackageRemoved(Ljava/lang/String;I)V
+Lcom/android/internal/content/PackageMonitor;->register(Landroid/content/Context;Landroid/os/Looper;Z)V
Lcom/android/internal/content/ReferrerIntent;-><init>(Landroid/content/Intent;Ljava/lang/String;)V
Lcom/android/internal/content/ReferrerIntent;->mReferrer:Ljava/lang/String;
Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
+Lcom/android/internal/logging/MetricsLogger;-><init>()V
+Lcom/android/internal/logging/MetricsLogger;->write(Landroid/metrics/LogMaker;)V
Lcom/android/internal/os/BatterySipper;-><init>(Lcom/android/internal/os/BatterySipper$DrainType;Landroid/os/BatteryStats$Uid;D)V
Lcom/android/internal/os/BatterySipper;->add(Lcom/android/internal/os/BatterySipper;)V
Lcom/android/internal/os/BatterySipper;->drainType:Lcom/android/internal/os/BatterySipper$DrainType;
@@ -3715,6 +3706,7 @@
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
+Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList;
@@ -3740,6 +3732,7 @@
Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File;
Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V
+Ldalvik/system/DexPathList;->addNativePath(Ljava/util/Collection;)V
Ldalvik/system/DexPathList;->definingContext:Ljava/lang/ClassLoader;
Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
Ldalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 4f878ac..fe10f41 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -100,11 +100,8 @@
Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V
Landroid/database/sqlite/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
Landroid/database/sqlite/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
-Landroid/graphics/AvoidXfermode;-><init>(IILandroid/graphics/AvoidXfermode$Mode;)V
Landroid/graphics/Bitmap;->createGraphicBufferHandle()Landroid/graphics/GraphicBuffer;
Landroid/graphics/Bitmap;->createHardwareBitmap(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;
-Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;)Z
-Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;Landroid/graphics/Region$Op;)Z
Landroid/graphics/drawable/Drawable;->isProjected()Z
Landroid/graphics/drawable/Drawable;->updateTintFilter(Landroid/graphics/PorterDuffColorFilter;Landroid/content/res/ColorStateList;Landroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuffColorFilter;
Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
@@ -152,8 +149,6 @@
Landroid/net/ConnectivityManager;->getActiveNetworkQuotaInfo()Landroid/net/NetworkQuotaInfo;
Landroid/net/ConnectivityManager;->setAirplaneMode(Z)V
Landroid/net/ConnectivityManager;->startNattKeepalive(Landroid/net/Network;ILandroid/net/ConnectivityManager$PacketKeepaliveCallback;Ljava/net/InetAddress;ILjava/net/InetAddress;)Landroid/net/ConnectivityManager$PacketKeepalive;
-Landroid/net/ConnectivityManager;->startUsingNetworkFeature(ILjava/lang/String;)I
-Landroid/net/ConnectivityManager;->stopUsingNetworkFeature(ILjava/lang/String;)I
Landroid/net/ConnectivityManager;->tether(Ljava/lang/String;)I
Landroid/net/ConnectivityManager;->untether(Ljava/lang/String;)I
Landroid/net/DhcpResults;-><init>()V
@@ -355,8 +350,6 @@
Landroid/os/Parcel;->readBlob()[B
Landroid/os/Parcel;->readStringArray()[Ljava/lang/String;
Landroid/os/Parcel;->writeBlob([B)V
-Landroid/os/PowerManager;->goToSleep(J)V
-Landroid/os/PowerManager;->isScreenBrightnessBoosted()Z
Landroid/os/Registrant;-><init>(Landroid/os/Handler;ILjava/lang/Object;)V
Landroid/os/Registrant;->clear()V
Landroid/os/Registrant;->notifyRegistrant()V
@@ -514,12 +507,6 @@
Landroid/telephony/TelephonyManager;->putIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
Landroid/telephony/TelephonyManager;->setPreferredNetworkType(II)Z
Landroid/text/TextUtils;->isPrintableAsciiOnly(Ljava/lang/CharSequence;)Z
-Landroid/util/FloatMath;->ceil(F)F
-Landroid/util/FloatMath;->cos(F)F
-Landroid/util/FloatMath;->exp(F)F
-Landroid/util/FloatMath;->floor(F)F
-Landroid/util/FloatMath;->sin(F)F
-Landroid/util/FloatMath;->sqrt(F)F
Landroid/util/IconDrawableFactory;->getBadgedIcon(Landroid/content/pm/PackageItemInfo;Landroid/content/pm/ApplicationInfo;I)Landroid/graphics/drawable/Drawable;
Landroid/util/IconDrawableFactory;->newInstance(Landroid/content/Context;)Landroid/util/IconDrawableFactory;
Landroid/util/LocalLog$ReadOnlyLocalLog;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 037a87b..3f66747 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2683,7 +2683,7 @@
// TODO(lifecycler): Can't switch to use #handleLaunchActivity() because it will try to
// call #reportSizeConfigurations(), but the server might not know anything about the
// activity if it was launched from LocalAcvitivyManager.
- return performLaunchActivity(r);
+ return performLaunchActivity(r, null /* customIntent */);
}
public final Activity getActivity(IBinder token) {
@@ -2768,7 +2768,7 @@
}
/** Core implementation of activity launch. */
- private Activity performLaunchActivity(ActivityClientRecord r) {
+ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
@@ -2838,6 +2838,9 @@
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
+ if (customIntent != null) {
+ activity.mIntent = customIntent;
+ }
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
@@ -2982,7 +2985,7 @@
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions) {
+ PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -3005,7 +3008,7 @@
}
WindowManagerGlobal.initialize();
- final Activity a = performLaunchActivity(r);
+ final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
@@ -4699,6 +4702,8 @@
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
PendingTransactionActions pendingActions, boolean startsNotResumed,
Configuration overrideConfig, String reason) {
+ // Preserve last used intent, it may be set from Activity#setIntent().
+ final Intent customIntent = r.activity.mIntent;
// Need to ensure state is saved.
if (!r.paused) {
performPauseActivity(r, false, reason, null /* pendingActions */);
@@ -4731,7 +4736,7 @@
r.startsNotResumed = startsNotResumed;
r.overrideConfig = overrideConfig;
- handleLaunchActivity(r, pendingActions);
+ handleLaunchActivity(r, pendingActions, customIntent);
}
@Override
@@ -5333,8 +5338,8 @@
}
}
}
- final List<String> oldPaths =
- sPackageManager.getPreviousCodePaths(packageName);
+ final ArrayList<String> oldPaths = new ArrayList<>();
+ LoadedApk.makePaths(this, pkgInfo.getApplicationInfo(), oldPaths);
pkgInfo.updateApplicationInfo(aInfo, oldPaths);
} catch (RemoteException e) {
}
@@ -5512,6 +5517,7 @@
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
+ VMRuntime.setProcessPackageName(data.appInfo.packageName);
if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 796e406..07048f9 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -338,7 +338,9 @@
/** @hide Any app start foreground service. */
public static final int OP_START_FOREGROUND = 76;
/** @hide */
- public static final int _NUM_OP = 77;
+ public static final int OP_BLUETOOTH_SCAN = 77;
+ /** @hide */
+ public static final int _NUM_OP = 78;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -580,6 +582,8 @@
/** @hide */
@SystemApi @TestApi
public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
+ /** @hide */
+ public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
// Warning: If an permission is added here it also has to be added to
// com.android.packageinstaller.permission.utils.EventLogger
@@ -717,6 +721,7 @@
OP_ACCEPT_HANDOVER, // ACCEPT_HANDOVER
OP_MANAGE_IPSEC_TUNNELS, // MANAGE_IPSEC_HANDOVERS
OP_START_FOREGROUND, // START_FOREGROUND
+ OP_COARSE_LOCATION, // BLUETOOTH_SCAN
};
/**
@@ -800,6 +805,7 @@
OPSTR_ACCEPT_HANDOVER,
OPSTR_MANAGE_IPSEC_TUNNELS,
OPSTR_START_FOREGROUND,
+ OPSTR_BLUETOOTH_SCAN,
};
/**
@@ -884,6 +890,7 @@
"ACCEPT_HANDOVER",
"MANAGE_IPSEC_TUNNELS",
"START_FOREGROUND",
+ "BLUETOOTH_SCAN",
};
/**
@@ -968,6 +975,7 @@
Manifest.permission.ACCEPT_HANDOVER,
null, // no permission for OP_MANAGE_IPSEC_TUNNELS
Manifest.permission.FOREGROUND_SERVICE,
+ null, // no permission for OP_BLUETOOTH_SCAN
};
/**
@@ -1053,6 +1061,7 @@
null, // ACCEPT_HANDOVER
null, // MANAGE_IPSEC_TUNNELS
null, // START_FOREGROUND
+ null, // maybe should be UserManager.DISALLOW_SHARE_LOCATION, //BLUETOOTH_SCAN
};
/**
@@ -1137,6 +1146,7 @@
false, // ACCEPT_HANDOVER
false, // MANAGE_IPSEC_HANDOVERS
false, // START_FOREGROUND
+ true, // BLUETOOTH_SCAN
};
/**
@@ -1220,6 +1230,7 @@
AppOpsManager.MODE_ALLOWED, // ACCEPT_HANDOVER
AppOpsManager.MODE_ERRORED, // MANAGE_IPSEC_TUNNELS
AppOpsManager.MODE_ALLOWED, // OP_START_FOREGROUND
+ AppOpsManager.MODE_ALLOWED, // OP_BLUETOOTH_SCAN
};
/**
@@ -1307,6 +1318,7 @@
false, // ACCEPT_HANDOVER
false, // MANAGE_IPSEC_TUNNELS
false, // START_FOREGROUND
+ false, // BLUETOOTH_SCAN
};
/**
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 7257044..0ed50f2 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -25,6 +25,8 @@
import dalvik.system.PathClassLoader;
+import java.util.Collection;
+
/** @hide */
public class ApplicationLoaders {
public static ApplicationLoaders getDefault() {
@@ -121,6 +123,17 @@
baseDexClassLoader.addDexPath(dexPath);
}
+ /**
+ * @hide
+ */
+ void addNative(ClassLoader classLoader, Collection<String> libPaths) {
+ if (!(classLoader instanceof PathClassLoader)) {
+ throw new IllegalStateException("class loader is not a PathClassLoader");
+ }
+ final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
+ baseDexClassLoader.addNativePath(libPaths);
+ }
+
private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>();
private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index ea0d703..d9c7cf3 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -18,6 +18,7 @@
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.TransactionExecutor;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -140,7 +141,7 @@
/** Perform activity launch. */
public abstract Activity handleLaunchActivity(ActivityThread.ActivityClientRecord r,
- PendingTransactionActions pendingActions);
+ PendingTransactionActions pendingActions, Intent customIntent);
/** Perform activity start. */
public abstract void handleStartActivity(ActivityThread.ActivityClientRecord r,
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index fc7d9a5..8c0cd23 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -90,6 +90,7 @@
public final class LoadedApk {
static final String TAG = "LoadedApk";
static final boolean DEBUG = false;
+ private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths";
private final ActivityThread mActivityThread;
final String mPackageName;
@@ -723,6 +724,10 @@
needToSetupJitProfiles = true;
}
+ if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) {
+ ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths);
+ }
+
if (addedPaths != null && addedPaths.size() > 0) {
final String add = TextUtils.join(File.pathSeparator, addedPaths);
ApplicationLoaders.getDefault().addPath(mClassLoader, add);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 9e47ced..ba355f9 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -76,6 +76,7 @@
private static final String ATT_CONTENT_TYPE = "content_type";
private static final String ATT_SHOW_BADGE = "show_badge";
private static final String ATT_USER_LOCKED = "locked";
+ private static final String ATT_FG_SERVICE_SHOWN = "fgservice";
private static final String ATT_GROUP = "group";
private static final String ATT_BLOCKABLE_SYSTEM = "blockable_system";
private static final String DELIMITER = ",";
@@ -144,6 +145,7 @@
// Bitwise representation of fields that have been changed by the user, preventing the app from
// making changes to these fields.
private int mUserLockedFields;
+ private boolean mFgServiceShown;
private boolean mVibrationEnabled;
private boolean mShowBadge = DEFAULT_SHOW_BADGE;
private boolean mDeleted = DEFAULT_DELETED;
@@ -200,6 +202,7 @@
mLights = in.readByte() != 0;
mVibration = in.createLongArray();
mUserLockedFields = in.readInt();
+ mFgServiceShown = in.readByte() != 0;
mVibrationEnabled = in.readByte() != 0;
mShowBadge = in.readByte() != 0;
mDeleted = in.readByte() != 0;
@@ -245,6 +248,7 @@
dest.writeByte(mLights ? (byte) 1 : (byte) 0);
dest.writeLongArray(mVibration);
dest.writeInt(mUserLockedFields);
+ dest.writeByte(mFgServiceShown ? (byte) 1 : (byte) 0);
dest.writeByte(mVibrationEnabled ? (byte) 1 : (byte) 0);
dest.writeByte(mShowBadge ? (byte) 1 : (byte) 0);
dest.writeByte(mDeleted ? (byte) 1 : (byte) 0);
@@ -281,6 +285,13 @@
/**
* @hide
*/
+ public void setFgServiceShown(boolean shown) {
+ mFgServiceShown = shown;
+ }
+
+ /**
+ * @hide
+ */
public void setDeleted(boolean deleted) {
mDeleted = deleted;
}
@@ -576,6 +587,13 @@
/**
* @hide
*/
+ public boolean isFgServiceShown() {
+ return mFgServiceShown;
+ }
+
+ /**
+ * @hide
+ */
public boolean isBlockableSystem() {
return mBlockableSystem;
}
@@ -620,6 +638,7 @@
setDeleted(safeBool(parser, ATT_DELETED, false));
setGroup(parser.getAttributeValue(null, ATT_GROUP));
lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
+ setFgServiceShown(safeBool(parser, ATT_FG_SERVICE_SHOWN, false));
setBlockableSystem(safeBool(parser, ATT_BLOCKABLE_SYSTEM, false));
}
@@ -724,6 +743,9 @@
if (getUserLockedFields() != 0) {
out.attribute(null, ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
}
+ if (isFgServiceShown()) {
+ out.attribute(null, ATT_FG_SERVICE_SHOWN, Boolean.toString(isFgServiceShown()));
+ }
if (canShowBadge()) {
out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
}
@@ -772,6 +794,7 @@
record.put(ATT_LIGHT_COLOR, Integer.toString(getLightColor()));
record.put(ATT_VIBRATION_ENABLED, Boolean.toString(shouldVibrate()));
record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
+ record.put(ATT_FG_SERVICE_SHOWN, Boolean.toString(isFgServiceShown()));
record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern()));
record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
record.put(ATT_DELETED, Boolean.toString(isDeleted()));
@@ -933,6 +956,7 @@
+ ", mLightColor=" + mLightColor
+ ", mVibration=" + Arrays.toString(mVibration)
+ ", mUserLockedFields=" + Integer.toHexString(mUserLockedFields)
+ + ", mFgServiceShown=" + mFgServiceShown
+ ", mVibrationEnabled=" + mVibrationEnabled
+ ", mShowBadge=" + mShowBadge
+ ", mDeleted=" + mDeleted
@@ -963,6 +987,7 @@
}
}
proto.write(NotificationChannelProto.USER_LOCKED_FIELDS, mUserLockedFields);
+ proto.write(NotificationChannelProto.FG_SERVICE_SHOWN, mFgServiceShown);
proto.write(NotificationChannelProto.IS_VIBRATION_ENABLED, mVibrationEnabled);
proto.write(NotificationChannelProto.SHOW_BADGE, mShowBadge);
proto.write(NotificationChannelProto.IS_DELETED, mDeleted);
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 7be82bf..6bae359 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -75,7 +75,7 @@
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
- client.handleLaunchActivity(r, pendingActions);
+ client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 5c803a5..43a2b4c 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -173,7 +173,8 @@
log("Transitioning to state: " + state);
switch (state) {
case ON_CREATE:
- mTransactionHandler.handleLaunchActivity(r, mPendingActions);
+ mTransactionHandler.handleLaunchActivity(r, mPendingActions,
+ null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 6b1222f..0269b6c 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -96,7 +96,8 @@
encryptionAware = directBootAware = orig.directBootAware;
}
- @Override public CharSequence loadLabel(PackageManager pm) {
+ /** @hide */
+ @Override public CharSequence loadUnsafeLabel(PackageManager pm) {
if (nonLocalizedLabel != null) {
return nonLocalizedLabel;
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2be33e9..c988fa9 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -644,8 +644,6 @@
boolean isPackageDeviceAdminOnAnyUser(String packageName);
- List<String> getPreviousCodePaths(in String packageName);
-
int getInstallReason(String packageName, int userId);
ParceledListSlice getSharedLibraries(in String packageName, int flags, int userId);
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 53ffd55..07fbfb5 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -43,6 +43,8 @@
*/
public class PackageItemInfo {
private static final float MAX_LABEL_SIZE_PX = 500f;
+ /** The maximum length of a safe label, in characters */
+ private static final int MAX_SAFE_LABEL_LENGTH = 50000;
private static volatile boolean sForceSafeLabels = false;
@@ -187,7 +189,8 @@
// If the label contains new line characters it may push the UI
// down to hide a part of it. Labels shouldn't have new line
// characters, so just truncate at the first time one is seen.
- final int labelLength = labelStr.length();
+ final int labelLength = Math.min(labelStr.length(), MAX_SAFE_LABEL_LENGTH);
+ final StringBuffer sb = new StringBuffer(labelLength);
int offset = 0;
while (offset < labelLength) {
final int codePoint = labelStr.codePointAt(offset);
@@ -199,14 +202,19 @@
break;
}
// replace all non-break space to " " in order to be trimmed
+ final int charCount = Character.charCount(codePoint);
if (type == Character.SPACE_SEPARATOR) {
- labelStr = labelStr.substring(0, offset) + " " + labelStr.substring(offset +
- Character.charCount(codePoint));
+ sb.append(' ');
+ } else {
+ sb.append(labelStr.charAt(offset));
+ if (charCount == 2) {
+ sb.append(labelStr.charAt(offset + 1));
+ }
}
- offset += Character.charCount(codePoint);
+ offset += charCount;
}
- labelStr = labelStr.trim();
+ labelStr = sb.toString().trim();
if (labelStr.isEmpty()) {
return packageName;
}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 19b5c45..193e56e 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1905,6 +1905,10 @@
* Return whether the screen has a wide color gamut and wide color gamut rendering
* is supported by this device.
*
+ * When true, it implies the screen is colorspace aware but not
+ * necessarily color-managed. The final colors may still be changed by the
+ * screen depending on user settings.
+ *
* @return true if the screen has a wide color gamut and wide color gamut rendering
* is supported, false otherwise
*/
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c58cde0..7adea6a8 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -128,6 +128,14 @@
private final ArrayList<WeakReference<Theme>> mThemeRefs = new ArrayList<>();
/**
+ * To avoid leaking WeakReferences to garbage collected Themes on the
+ * mThemeRefs list, we flush the list of stale references any time the
+ * mThemeRefNextFlushSize is reached.
+ */
+ private static final int MIN_THEME_REFS_FLUSH_SIZE = 32;
+ private int mThemeRefsNextFlushSize = MIN_THEME_REFS_FLUSH_SIZE;
+
+ /**
* Returns the most appropriate default theme for the specified target SDK version.
* <ul>
* <li>Below API 11: Gingerbread
@@ -1770,6 +1778,13 @@
theme.setImpl(mResourcesImpl.newThemeImpl());
synchronized (mThemeRefs) {
mThemeRefs.add(new WeakReference<>(theme));
+
+ // Clean up references to garbage collected themes
+ if (mThemeRefs.size() > mThemeRefsNextFlushSize) {
+ mThemeRefs.removeIf(ref -> ref.get() == null);
+ mThemeRefsNextFlushSize = Math.max(MIN_THEME_REFS_FLUSH_SIZE,
+ 2 * mThemeRefs.size());
+ }
}
return theme;
}
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 36c5deb..8c256be 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -56,7 +56,7 @@
/**
* Tells statsd that the device is about to shutdown.
*/
- void informDeviceShutdown(boolean isShutdown);
+ void informDeviceShutdown();
/**
* Inform statsd what the version and package are for each uid. Note that each array should
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9b20ed2..11afd21 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -157,8 +157,9 @@
public static final String DISALLOW_CONFIG_LOCALE = "no_config_locale";
/**
- * Specifies if a user is disallowed from installing applications.
- * The default value is <code>false</code>.
+ * Specifies if a user is disallowed from installing applications. This user restriction also
+ * prevents device owners and profile owners installing apps. The default value is
+ * {@code false}.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 9e3e386..5c99f6c 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -312,7 +312,7 @@
* {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
*/
public File getInternalPathForUser(int userId) {
- if (type == TYPE_PUBLIC && !isVisible()) {
+ if (type == TYPE_PUBLIC) {
// TODO: plumb through cleaner path from vold
return new File(path.replace("/storage/", "/mnt/media_rw/"));
} else {
diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java
index f15e1a1..2dd0117 100644
--- a/core/java/android/util/apk/ApkVerityBuilder.java
+++ b/core/java/android/util/apk/ApkVerityBuilder.java
@@ -134,7 +134,7 @@
assertSigningBlockAlignedAndHasFullPages(signatureInfo);
long signingBlockSize =
signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset;
- long dataSize = apk.length() - signingBlockSize - ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE;
+ long dataSize = apk.length() - signingBlockSize;
int[] levelOffset = calculateVerityLevelOffset(dataSize);
if (treeOutput != null) {
@@ -346,8 +346,8 @@
buffer.putLong(fileSize); // original file size
- buffer.put((byte) 0); // auth block offset, disabled here
- buffer.put((byte) 2); // extension count
+ buffer.put((byte) 2); // authenticated extension count
+ buffer.put((byte) 0); // unauthenticated extension count
buffer.put(salt); // salt (8 bytes)
skip(buffer, 22); // reserved
@@ -359,12 +359,6 @@
long signingBlockSize, long eocdOffset) {
// Snapshot of the FSVerity structs (subject to change once upstreamed).
//
- // struct fsverity_extension {
- // __le16 length;
- // u8 type;
- // u8 reserved[5];
- // };
- //
// struct fsverity_extension_elide {
// __le64 offset;
// __le64 length;
@@ -382,10 +376,10 @@
// struct fsverity_extension #1
final int kSizeOfFsverityElidedExtension = 16;
- buffer.putShort((short) // total size of extension, padded to 64-bit alignment
- (kSizeOfFsverityExtensionHeader + kSizeOfFsverityElidedExtension));
- buffer.put((byte) 0); // ID of elide extension
- skip(buffer, 5); // reserved
+ // First field is total size of extension, padded to 64-bit alignment
+ buffer.putInt(kSizeOfFsverityExtensionHeader + kSizeOfFsverityElidedExtension);
+ buffer.putShort((short) 1); // ID of elide extension
+ skip(buffer, 2); // reserved
// struct fsverity_extension_elide
buffer.putLong(signingBlockOffset);
@@ -398,9 +392,9 @@
+ 8 // offset size
+ ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE;
- buffer.putShort((short) kTotalSize);
- buffer.put((byte) 1); // ID of patch extension
- skip(buffer, 5); // reserved
+ buffer.putInt(kTotalSize); // Total size of extension, padded to 64-bit alignment
+ buffer.putShort((short) 2); // ID of patch extension
+ skip(buffer, 2); // reserved
// struct fsverity_extension_patch
buffer.putLong(eocdOffset + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET); // offset
@@ -412,7 +406,7 @@
if (kPadding == kExtensionSizeAlignment) {
kPadding = 0;
}
- skip(buffer, kPadding); // padding
+ skip(buffer, kPadding); // padding
}
buffer.flip();
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5deee11..ed8b005 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1580,6 +1580,20 @@
*/
public Transaction destroy(SurfaceControl sc) {
sc.checkNotReleased();
+
+ /**
+ * Perhaps it's safer to transfer the close guard to the Transaction
+ * but then we have a whole wonky scenario regarding merging, multiple
+ * close-guards per transaction etc...the whole scenario is kind of wonky
+ * and it seems really we'd like to just be able to call release here
+ * but the WindowManager has some code that looks like
+ * --- destroyInTransaction(a)
+ * --- reparentChildrenInTransaction(a)
+ * so we need to ensure the SC remains valid until the transaction
+ * is applied.
+ */
+ sc.mCloseGuard.close();
+
nativeDestroy(mNativeObject, sc.mNativeObject);
return this;
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index da47bcb..24f531d 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -114,9 +114,10 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @StringDef({WIDGET_TYPE_TEXTVIEW, WIDGET_TYPE_WEBVIEW, WIDGET_TYPE_EDITTEXT,
- WIDGET_TYPE_EDIT_WEBVIEW, WIDGET_TYPE_CUSTOM_TEXTVIEW, WIDGET_TYPE_CUSTOM_EDITTEXT,
- WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW, WIDGET_TYPE_UNKNOWN})
+ @StringDef({WIDGET_TYPE_TEXTVIEW, WIDGET_TYPE_EDITTEXT, WIDGET_TYPE_UNSELECTABLE_TEXTVIEW,
+ WIDGET_TYPE_WEBVIEW, WIDGET_TYPE_EDIT_WEBVIEW, WIDGET_TYPE_CUSTOM_TEXTVIEW,
+ WIDGET_TYPE_CUSTOM_EDITTEXT, WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW,
+ WIDGET_TYPE_UNKNOWN})
@interface WidgetType {}
/** The widget involved in the text classification session is a standard
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 4db3607..a22f345 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -104,8 +104,16 @@
sReceiverInfo.set(ri);
}
ri.addView(this);
+ // The view may not be added to the view hierarchy immediately right after setTime()
+ // is called which means it won't get any update from intents before being added.
+ // In such case, the view might show the incorrect relative time after being added to the
+ // view hierarchy until the next update intent comes.
+ // So we update the time here if mShowRelativeTime is enabled to prevent this case.
+ if (mShowRelativeTime) {
+ update();
+ }
}
-
+
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 08c4dc9..929496f 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -38,7 +38,6 @@
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.DisplayListCanvas;
-import android.view.LayoutInflater;
import android.view.PixelCopy;
import android.view.RenderNode;
import android.view.Surface;
@@ -71,8 +70,6 @@
private final int[] mViewCoordinatesInSurface;
// The window containing the magnifier.
private InternalPopupWindow mWindow;
- // The center coordinates of the window containing the magnifier.
- private final Point mWindowCoords = new Point();
// The width of the window containing the magnifier.
private final int mWindowWidth;
// The height of the window containing the magnifier.
@@ -87,8 +84,18 @@
private final float mWindowElevation;
// The corner radius of the window containing the magnifier.
private final float mWindowCornerRadius;
- // The center coordinates of the content that is to be magnified.
+ // The parent surface for the magnifier surface.
+ private SurfaceInfo mParentSurface;
+ // The surface where the content will be copied from.
+ private SurfaceInfo mContentCopySurface;
+ // The center coordinates of the window containing the magnifier.
+ private final Point mWindowCoords = new Point();
+ // The center coordinates of the content to be magnified,
+ // which can potentially contain a region outside the magnified view.
private final Point mCenterZoomCoords = new Point();
+ // The center coordinates of the content to be magnified,
+ // clamped inside the visible region of the magnified view.
+ private final Point mClampedCenterZoomCoords = new Point();
// Variables holding previous states, used for detecting redundant calls and invalidation.
private final Point mPrevStartCoordsInSurface = new Point(
NONEXISTENT_PREVIOUS_CONFIG_VALUE, NONEXISTENT_PREVIOUS_CONFIG_VALUE);
@@ -108,8 +115,6 @@
public Magnifier(@NonNull View view) {
mView = Preconditions.checkNotNull(view);
final Context context = mView.getContext();
- final View content = LayoutInflater.from(context).inflate(R.layout.magnifier, null);
- content.findViewById(R.id.magnifier_inner).setClipToOutline(true);
mWindowWidth = context.getResources().getDimensionPixelSize(R.dimen.magnifier_width);
mWindowHeight = context.getResources().getDimensionPixelSize(R.dimen.magnifier_height);
mWindowElevation = context.getResources().getDimension(R.dimen.magnifier_elevation);
@@ -155,31 +160,17 @@
xPosInView = Math.max(0, Math.min(xPosInView, mView.getWidth()));
yPosInView = Math.max(0, Math.min(yPosInView, mView.getHeight()));
- configureCoordinates(xPosInView, yPosInView);
+ obtainSurfaces();
+ obtainContentCoordinates(xPosInView, yPosInView);
+ obtainWindowCoordinates();
- // Clamp the startX location to avoid magnifying content which does not belong
- // to the magnified view. This will not take into account overlapping views.
- final Rect viewVisibleRegion = new Rect();
- mView.getGlobalVisibleRect(viewVisibleRegion);
- if (mView.getViewRootImpl() != null) {
- // Clamping coordinates relative to the surface, not to the window.
- final Rect surfaceInsets = mView.getViewRootImpl().mWindowAttributes.surfaceInsets;
- viewVisibleRegion.offset(surfaceInsets.left, surfaceInsets.top);
- }
- if (mView instanceof SurfaceView) {
- // If we copy content from a SurfaceView, clamp coordinates relative to it.
- viewVisibleRegion.offset(-mViewCoordinatesInSurface[0], -mViewCoordinatesInSurface[1]);
- }
- final int startX = Math.max(viewVisibleRegion.left, Math.min(
- mCenterZoomCoords.x - mBitmapWidth / 2,
- viewVisibleRegion.right - mBitmapWidth));
- final int startY = mCenterZoomCoords.y - mBitmapHeight / 2;
-
+ final int startX = mClampedCenterZoomCoords.x - mBitmapWidth / 2;
+ final int startY = mClampedCenterZoomCoords.y - mBitmapHeight / 2;
if (xPosInView != mPrevPosInView.x || yPosInView != mPrevPosInView.y) {
if (mWindow == null) {
synchronized (mLock) {
mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
- getValidParentSurfaceForMagnifier(),
+ mParentSurface.mSurface,
mWindowWidth, mWindowHeight, mWindowElevation, mWindowCornerRadius,
Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
mCallback);
@@ -213,6 +204,7 @@
*/
public void update() {
if (mWindow != null) {
+ obtainSurfaces();
// Update the content shown in the magnifier.
performPixelCopy(mPrevStartCoordsInSurface.x, mPrevStartCoordsInSurface.y,
false /* update window position */);
@@ -257,26 +249,53 @@
mWindow.mLastDrawContentPositionY - surfaceInsets.top);
}
- @Nullable
- private Surface getValidParentSurfaceForMagnifier() {
+ /**
+ * Retrieves the surfaces used by the magnifier:
+ * - a parent surface for the magnifier surface. This will usually be the main app window.
+ * - a surface where the magnified content will be copied from. This will be the main app
+ * window unless the magnified view is a SurfaceView, in which case its backing surface
+ * will be used.
+ */
+ private void obtainSurfaces() {
+ // Get the main window surface.
+ SurfaceInfo validMainWindowSurface = SurfaceInfo.NULL;
if (mView.getViewRootImpl() != null) {
- final Surface mainWindowSurface = mView.getViewRootImpl().mSurface;
+ final ViewRootImpl viewRootImpl = mView.getViewRootImpl();
+ final Surface mainWindowSurface = viewRootImpl.mSurface;
if (mainWindowSurface != null && mainWindowSurface.isValid()) {
- return mainWindowSurface;
+ final Rect surfaceInsets = viewRootImpl.mWindowAttributes.surfaceInsets;
+ final int surfaceWidth =
+ viewRootImpl.getWidth() + surfaceInsets.left + surfaceInsets.right;
+ final int surfaceHeight =
+ viewRootImpl.getHeight() + surfaceInsets.top + surfaceInsets.bottom;
+ validMainWindowSurface =
+ new SurfaceInfo(mainWindowSurface, surfaceWidth, surfaceHeight, true);
}
}
+ // Get the surface backing the magnified view, if it is a SurfaceView.
+ SurfaceInfo validSurfaceViewSurface = SurfaceInfo.NULL;
if (mView instanceof SurfaceView) {
- final Surface surfaceViewSurface = ((SurfaceView) mView).getHolder().getSurface();
+ final SurfaceHolder surfaceHolder = ((SurfaceView) mView).getHolder();
+ final Surface surfaceViewSurface = surfaceHolder.getSurface();
if (surfaceViewSurface != null && surfaceViewSurface.isValid()) {
- return surfaceViewSurface;
+ final Rect surfaceFrame = surfaceHolder.getSurfaceFrame();
+ validSurfaceViewSurface = new SurfaceInfo(surfaceViewSurface,
+ surfaceFrame.right, surfaceFrame.bottom, false);
}
}
- return null;
+
+ // Choose the parent surface for the magnifier and the source surface for the content.
+ mParentSurface = validMainWindowSurface != SurfaceInfo.NULL
+ ? validMainWindowSurface : validSurfaceViewSurface;
+ mContentCopySurface = mView instanceof SurfaceView
+ ? validSurfaceViewSurface : validMainWindowSurface;
}
- private void configureCoordinates(final float xPosInView, final float yPosInView) {
- // Compute the coordinates of the center of the content going to be displayed in the
- // magnifier. These are relative to the surface the content is copied from.
+ /**
+ * Computes the coordinates of the center of the content going to be displayed in the
+ * magnifier. These are relative to the surface the content is copied from.
+ */
+ private void obtainContentCoordinates(final float xPosInView, final float yPosInView) {
final float posX;
final float posY;
mView.getLocationInSurface(mViewCoordinatesInSurface);
@@ -291,78 +310,59 @@
mCenterZoomCoords.x = Math.round(posX);
mCenterZoomCoords.y = Math.round(posY);
+ // Clamp the x location to avoid magnifying content which does not belong
+ // to the magnified view. This will not take into account overlapping views.
+ final Rect viewVisibleRegion = new Rect();
+ mView.getGlobalVisibleRect(viewVisibleRegion);
+ if (mView.getViewRootImpl() != null) {
+ // Clamping coordinates relative to the surface, not to the window.
+ final Rect surfaceInsets = mView.getViewRootImpl().mWindowAttributes.surfaceInsets;
+ viewVisibleRegion.offset(surfaceInsets.left, surfaceInsets.top);
+ }
+ if (mView instanceof SurfaceView) {
+ // If we copy content from a SurfaceView, clamp coordinates relative to it.
+ viewVisibleRegion.offset(-mViewCoordinatesInSurface[0], -mViewCoordinatesInSurface[1]);
+ }
+ mClampedCenterZoomCoords.x = Math.max(viewVisibleRegion.left + mBitmapWidth / 2, Math.min(
+ mCenterZoomCoords.x, viewVisibleRegion.right - mBitmapWidth / 2));
+ mClampedCenterZoomCoords.y = mCenterZoomCoords.y;
+ }
+
+ private void obtainWindowCoordinates() {
// Compute the position of the magnifier window. Again, this has to be relative to the
// surface of the magnified view, as this surface is the parent of the magnifier surface.
final int verticalOffset = mView.getContext().getResources().getDimensionPixelSize(
R.dimen.magnifier_offset);
mWindowCoords.x = mCenterZoomCoords.x - mWindowWidth / 2;
mWindowCoords.y = mCenterZoomCoords.y - mWindowHeight / 2 - verticalOffset;
- if (mView instanceof SurfaceView && mView.getViewRootImpl() != null) {
- // TODO: deduplicate against the first part of #getValidParentSurfaceForMagnifier()
- final Surface mainWindowSurface = mView.getViewRootImpl().mSurface;
- if (mainWindowSurface != null && mainWindowSurface.isValid()) {
- mWindowCoords.x += mViewCoordinatesInSurface[0];
- mWindowCoords.y += mViewCoordinatesInSurface[1];
- }
+ if (mParentSurface != mContentCopySurface) {
+ mWindowCoords.x += mViewCoordinatesInSurface[0];
+ mWindowCoords.y += mViewCoordinatesInSurface[1];
}
}
private void performPixelCopy(final int startXInSurface, final int startYInSurface,
final boolean updateWindowPosition) {
- // Get the view surface where the content will be copied from.
- final Surface surface;
- final int surfaceWidth;
- final int surfaceHeight;
- if (mView instanceof SurfaceView) {
- final SurfaceHolder surfaceHolder = ((SurfaceView) mView).getHolder();
- surface = surfaceHolder.getSurface();
- surfaceWidth = surfaceHolder.getSurfaceFrame().right;
- surfaceHeight = surfaceHolder.getSurfaceFrame().bottom;
- } else if (mView.getViewRootImpl() != null) {
- final ViewRootImpl viewRootImpl = mView.getViewRootImpl();
- surface = viewRootImpl.mSurface;
- final Rect surfaceInsets = viewRootImpl.mWindowAttributes.surfaceInsets;
- surfaceWidth = viewRootImpl.getWidth() + surfaceInsets.left + surfaceInsets.right;
- surfaceHeight = viewRootImpl.getHeight() + surfaceInsets.top + surfaceInsets.bottom;
- } else {
- surface = null;
- surfaceWidth = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
- surfaceHeight = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
- }
-
- if (surface == null || !surface.isValid()) {
+ if (mContentCopySurface.mSurface == null || !mContentCopySurface.mSurface.isValid()) {
return;
}
-
// Clamp copy coordinates inside the surface to avoid displaying distorted content.
final int clampedStartXInSurface = Math.max(0,
- Math.min(startXInSurface, surfaceWidth - mBitmapWidth));
+ Math.min(startXInSurface, mContentCopySurface.mWidth - mBitmapWidth));
final int clampedStartYInSurface = Math.max(0,
- Math.min(startYInSurface, surfaceHeight - mBitmapHeight));
+ Math.min(startYInSurface, mContentCopySurface.mHeight - mBitmapHeight));
// Clamp window coordinates inside the parent surface, to avoid displaying
// the magnifier out of screen or overlapping with system insets.
- Rect windowBounds = null;
- if (mView.getViewRootImpl() != null) {
- // TODO: deduplicate against the first part of #getValidParentSurfaceForMagnifier()
- // TODO: deduplicate against the first part of the current method
- final ViewRootImpl viewRootImpl = mView.getViewRootImpl();
- final Surface parentSurface = viewRootImpl.mSurface;
- final Rect surfaceInsets = viewRootImpl.mWindowAttributes.surfaceInsets;
- final int parentWidth =
- viewRootImpl.getWidth() + surfaceInsets.left + surfaceInsets.right;
- final int parentHeight =
- viewRootImpl.getHeight() + surfaceInsets.top + surfaceInsets.bottom;
- if (parentSurface != null && parentSurface.isValid()) {
- final Rect systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
- windowBounds = new Rect(systemInsets.left, systemInsets.top,
- parentWidth - systemInsets.right, parentHeight - systemInsets.bottom);
- }
+ final Rect windowBounds;
+ if (mParentSurface.mIsMainWindowSurface) {
+ final Rect systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
+ windowBounds = new Rect(systemInsets.left, systemInsets.top,
+ mParentSurface.mWidth - systemInsets.right,
+ mParentSurface.mHeight - systemInsets.bottom);
+ } else {
+ windowBounds = new Rect(0, 0, mParentSurface.mWidth, mParentSurface.mHeight);
}
- if (windowBounds == null && mView instanceof SurfaceView) {
- windowBounds = ((SurfaceView) mView).getHolder().getSurfaceFrame();
- }
-
final int windowCoordsX = Math.max(windowBounds.left,
Math.min(windowBounds.right - mWindowWidth, mWindowCoords.x));
final int windowCoordsY = Math.max(windowBounds.top,
@@ -376,7 +376,7 @@
final InternalPopupWindow currentWindowInstance = mWindow;
final Bitmap bitmap =
Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ARGB_8888);
- PixelCopy.request(surface, mPixelCopyRequestRect, bitmap,
+ PixelCopy.request(mContentCopySurface.mSurface, mPixelCopyRequestRect, bitmap,
result -> {
synchronized (mLock) {
if (mWindow != currentWindowInstance) {
@@ -396,6 +396,26 @@
}
/**
+ * Contains a surface and metadata corresponding to it.
+ */
+ private static class SurfaceInfo {
+ public static final SurfaceInfo NULL = new SurfaceInfo(null, 0, 0, false);
+
+ private Surface mSurface;
+ private int mWidth;
+ private int mHeight;
+ private boolean mIsMainWindowSurface;
+
+ SurfaceInfo(final Surface surface, final int width, final int height,
+ final boolean isMainWindowSurface) {
+ mSurface = surface;
+ mWidth = width;
+ mHeight = height;
+ mIsMainWindowSurface = isMainWindowSurface;
+ }
+ }
+
+ /**
* Magnifier's own implementation of PopupWindow-similar floating window.
* This exists to ensure frame-synchronization between window position updates and window
* content updates. By using a PopupWindow, these events would happen in different frames,
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index a075705..b591163 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -85,6 +85,14 @@
protected abstract Uri buildNotificationUri(String docId);
+ /**
+ * Callback indicating that the given document has been modified. This gives
+ * the provider a hook to invalidate cached data, such as {@code sdcardfs}.
+ */
+ protected void onDocIdChanged(String docId) {
+ // Default is no-op
+ }
+
@Override
public boolean onCreate() {
throw new UnsupportedOperationException(
@@ -185,6 +193,7 @@
throw new IllegalStateException("Failed to mkdir " + file);
}
childId = getDocIdForFile(file);
+ onDocIdChanged(childId);
addFolderToMediaStore(getFileForDocId(childId, true));
} else {
try {
@@ -192,6 +201,7 @@
throw new IllegalStateException("Failed to touch " + file);
}
childId = getDocIdForFile(file);
+ onDocIdChanged(childId);
} catch (IOException e) {
throw new IllegalStateException("Failed to touch " + file + ": " + e);
}
@@ -227,16 +237,20 @@
final File before = getFileForDocId(docId);
final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
- final File visibleFileBefore = getFileForDocId(docId, true);
if (!before.renameTo(after)) {
throw new IllegalStateException("Failed to rename to " + after);
}
final String afterDocId = getDocIdForFile(after);
- moveInMediaStore(visibleFileBefore, getFileForDocId(afterDocId, true));
+ onDocIdChanged(docId);
+ onDocIdChanged(afterDocId);
+
+ final File beforeVisibleFile = getFileForDocId(docId, true);
+ final File afterVisibleFile = getFileForDocId(afterDocId, true);
+ moveInMediaStore(beforeVisibleFile, afterVisibleFile);
if (!TextUtils.equals(docId, afterDocId)) {
- scanFile(after);
+ scanFile(afterVisibleFile);
return afterDocId;
} else {
return null;
@@ -259,6 +273,8 @@
}
final String docId = getDocIdForFile(after);
+ onDocIdChanged(sourceDocumentId);
+ onDocIdChanged(docId);
moveInMediaStore(visibleFileBefore, getFileForDocId(docId, true));
return docId;
@@ -308,6 +324,7 @@
throw new IllegalStateException("Failed to delete " + file);
}
+ onDocIdChanged(docId);
removeFromMediaStore(visibleFile, isDirectory);
}
@@ -418,7 +435,10 @@
try {
// When finished writing, kick off media scanner
return ParcelFileDescriptor.open(
- file, pfdMode, mHandler, (IOException e) -> scanFile(visibleFile));
+ file, pfdMode, mHandler, (IOException e) -> {
+ onDocIdChanged(documentId);
+ scanFile(visibleFile);
+ });
} catch (IOException e) {
throw new FileNotFoundException("Failed to open for writing: " + e);
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index a1e6fd8..c388148 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -282,7 +282,10 @@
}
}
- private static void createNativeLibrarySubdir(File path) throws IOException {
+ /**
+ * @hide
+ */
+ public static void createNativeLibrarySubdir(File path) throws IOException {
if (!path.isDirectory()) {
path.delete();
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 98afebc5..c4d08c7 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -56,8 +56,6 @@
private static final boolean USE_NATIVE_PARSING = true;
private static final boolean SANITY_CHECK_NATIVE = false;
- /** Path to {@code /proc/net/dev}. */
- private final File mStatsIfaceDev;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
@@ -133,47 +131,16 @@
@VisibleForTesting
public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
- mStatsIfaceDev = new File(procRoot, "net/dev");
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
mUseBpfStats = useBpfStats;
}
- @VisibleForTesting
- public NetworkStats readNetworkStatsIfaceDev() throws IOException {
- final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
+ public NetworkStats readBpfNetworkStatsDev() throws IOException {
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
-
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(mStatsIfaceDev));
-
- // skip first two header lines
- reader.readLine();
- reader.readLine();
-
- // parse remaining lines
- String line;
- while ((line = reader.readLine()) != null) {
- String[] values = line.trim().split("\\:?\\s+");
- entry.iface = values[0];
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.rxBytes = Long.parseLong(values[1]);
- entry.rxPackets = Long.parseLong(values[2]);
- entry.txBytes = Long.parseLong(values[9]);
- entry.txPackets = Long.parseLong(values[10]);
- stats.addValues(entry);
- }
- } catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing stats", e);
- } finally {
- IoUtils.closeQuietly(reader);
- StrictMode.setThreadPolicy(savedPolicy);
+ if (nativeReadNetworkStatsDev(stats) != 0) {
+ throw new IOException("Failed to parse bpf iface stats");
}
return stats;
}
@@ -188,9 +155,9 @@
*/
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
- // Return the stats get from /proc/net/dev if switched to bpf module.
+ // Return xt_bpf stats if switched to bpf module.
if (mUseBpfStats)
- return readNetworkStatsIfaceDev();
+ return readBpfNetworkStatsDev();
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
@@ -244,9 +211,9 @@
*/
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
- // Return the stats get from /proc/net/dev if qtaguid module is replaced.
+ // Return xt_bpf stats if qtaguid module is replaced.
if (mUseBpfStats)
- return readNetworkStatsIfaceDev();
+ return readBpfNetworkStatsDev();
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
@@ -408,4 +375,7 @@
@VisibleForTesting
public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
+
+ @VisibleForTesting
+ public static native int nativeReadNetworkStatsDev(NetworkStats stats);
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index cc95df7..2db5739 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -308,10 +308,8 @@
public void onDraw(Canvas c) {
super.onDraw(c);
- // When we are resizing, we need the fallback background to cover the area where we have our
- // system bar background views as the navigation bar will be hidden during resizing.
- mBackgroundFallback.draw(isResizing() ? this : mContentRoot, mContentRoot, c,
- mWindow.mContentParent);
+ mBackgroundFallback.draw(this, mContentRoot, c, mWindow.mContentParent,
+ mStatusColorViewState.view, mNavigationColorViewState.view);
}
@Override
diff --git a/core/java/com/android/internal/widget/BackgroundFallback.java b/core/java/com/android/internal/widget/BackgroundFallback.java
index 309f80c..2b05f1e 100644
--- a/core/java/com/android/internal/widget/BackgroundFallback.java
+++ b/core/java/com/android/internal/widget/BackgroundFallback.java
@@ -46,8 +46,11 @@
* @param root The view group containing the content.
* @param c The canvas to draw the background onto.
* @param content The view where the actual app content is contained in.
+ * @param coveringView1 A potentially opaque view drawn atop the content
+ * @param coveringView2 A potentially opaque view drawn atop the content
*/
- public void draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content) {
+ public void draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content,
+ View coveringView1, View coveringView2) {
if (!hasFallback()) {
return;
}
@@ -55,6 +58,10 @@
// Draw the fallback in the padding.
final int width = boundsView.getWidth();
final int height = boundsView.getHeight();
+
+ final int rootOffsetX = root.getLeft();
+ final int rootOffsetY = root.getTop();
+
int left = width;
int top = height;
int right = 0;
@@ -71,17 +78,58 @@
((ViewGroup) child).getChildCount() == 0) {
continue;
}
- } else if (child.getVisibility() != View.VISIBLE || childBg == null ||
- childBg.getOpacity() != PixelFormat.OPAQUE) {
+ } else if (child.getVisibility() != View.VISIBLE || !isOpaque(childBg)) {
// Potentially translucent or invisible children don't count, and we assume
// the content view will cover the whole area if we're in a background
// fallback situation.
continue;
}
- left = Math.min(left, child.getLeft());
- top = Math.min(top, child.getTop());
- right = Math.max(right, child.getRight());
- bottom = Math.max(bottom, child.getBottom());
+ left = Math.min(left, rootOffsetX + child.getLeft());
+ top = Math.min(top, rootOffsetY + child.getTop());
+ right = Math.max(right, rootOffsetX + child.getRight());
+ bottom = Math.max(bottom, rootOffsetY + child.getBottom());
+ }
+
+ // If one of the bar backgrounds is a solid color and covers the entire padding on a side
+ // we can drop that padding.
+ boolean eachBarCoversTopInY = true;
+ for (int i = 0; i < 2; i++) {
+ View v = (i == 0) ? coveringView1 : coveringView2;
+ if (v == null || v.getVisibility() != View.VISIBLE
+ || v.getAlpha() != 1f || !isOpaque(v.getBackground())) {
+ eachBarCoversTopInY = false;
+ continue;
+ }
+
+ // Bar covers entire left padding
+ if (v.getTop() <= 0 && v.getBottom() >= height
+ && v.getLeft() <= 0 && v.getRight() >= left) {
+ left = 0;
+ }
+ // Bar covers entire right padding
+ if (v.getTop() <= 0 && v.getBottom() >= height
+ && v.getLeft() <= right && v.getRight() >= width) {
+ right = width;
+ }
+ // Bar covers entire top padding
+ if (v.getTop() <= 0 && v.getBottom() >= top
+ && v.getLeft() <= 0 && v.getRight() >= width) {
+ top = 0;
+ }
+ // Bar covers entire bottom padding
+ if (v.getTop() <= bottom && v.getBottom() >= height
+ && v.getLeft() <= 0 && v.getRight() >= width) {
+ bottom = height;
+ }
+
+ eachBarCoversTopInY &= v.getTop() <= 0 && v.getBottom() >= top;
+ }
+
+ // Special case: Sometimes, both covering views together may cover the top inset, but
+ // neither does on its own.
+ if (eachBarCoversTopInY && (viewsCoverEntireWidth(coveringView1, coveringView2, width)
+ || viewsCoverEntireWidth(coveringView2, coveringView1, width))) {
+ top = 0;
}
if (left >= right || top >= bottom) {
@@ -106,4 +154,24 @@
mBackgroundFallback.draw(c);
}
}
+
+ private boolean isOpaque(Drawable childBg) {
+ return childBg != null && childBg.getOpacity() == PixelFormat.OPAQUE;
+ }
+
+ /**
+ * Returns true if {@code view1} starts before or on {@code 0} and extends at least
+ * up to {@code view2}, and that view extends at least to {@code width}.
+ *
+ * @param view1 the first view to check if it covers the width
+ * @param view2 the second view to check if it covers the width
+ * @param width the width to check for
+ * @return returns true if both views together cover the entire width (and view1 is to the left
+ * of view2)
+ */
+ private boolean viewsCoverEntireWidth(View view1, View view2, int width) {
+ return view1.getLeft() <= 0
+ && view1.getRight() >= view2.getLeft()
+ && view2.getRight() >= width;
+ }
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 1e7c11e..e143498 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -28,8 +28,6 @@
import android.widget.RemoteViews;
import android.widget.TextView;
-import com.android.internal.R;
-
/**
* A TextView that can float around an image on the end.
*
@@ -44,9 +42,7 @@
/** Resolved layout direction */
private int mResolvedDirection = LAYOUT_DIRECTION_UNDEFINED;
private int mMaxLinesForHeight = -1;
- private boolean mFirstMeasure = true;
private int mLayoutMaxLines = -1;
- private boolean mBlockLayouts;
private int mImageEndMargin;
public ImageFloatingTextView(Context context) {
@@ -122,30 +118,31 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int height = MeasureSpec.getSize(heightMeasureSpec);
- // Lets calculate how many lines the given measurement allows us.
- int availableHeight = height - mPaddingTop - mPaddingBottom;
- int maxLines = availableHeight / getLineHeight();
- maxLines = Math.max(1, maxLines);
- if (getMaxLines() > 0) {
- maxLines = Math.min(getMaxLines(), maxLines);
- }
- if (maxLines != mMaxLinesForHeight) {
- mMaxLinesForHeight = maxLines;
- if (getLayout() != null && mMaxLinesForHeight != mLayoutMaxLines) {
- // Invalidate layout.
- mBlockLayouts = true;
- setHint(getHint());
- mBlockLayouts = false;
- }
+ int availableHeight = MeasureSpec.getSize(heightMeasureSpec) - mPaddingTop - mPaddingBottom;
+ if (getLayout() != null && getLayout().getHeight() != availableHeight) {
+ // We've been measured before and the new size is different than before, lets make sure
+ // we reset the maximum lines, otherwise we may be cut short
+ mMaxLinesForHeight = -1;
+ nullLayouts();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- public void requestLayout() {
- if (!mBlockLayouts) {
- super.requestLayout();
+ Layout layout = getLayout();
+ if (layout.getHeight() > availableHeight) {
+ // With the existing layout, not all of our lines fit on the screen, let's find the
+ // first one that fits and ellipsize at that one.
+ int maxLines = layout.getLineCount() - 1;
+ while (maxLines > 1 && layout.getLineBottom(maxLines - 1) > availableHeight) {
+ maxLines--;
+ }
+ if (getMaxLines() > 0) {
+ maxLines = Math.min(getMaxLines(), maxLines);
+ }
+ // Only if the number of lines is different from the current layout, we recreate it.
+ if (maxLines != mLayoutMaxLines) {
+ mMaxLinesForHeight = maxLines;
+ nullLayouts();
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
}
}
@@ -157,7 +154,8 @@
mResolvedDirection = layoutDirection;
if (mIndentLines > 0) {
// Invalidate layout.
- setHint(getHint());
+ nullLayouts();
+ requestLayout();
}
}
}
@@ -175,7 +173,8 @@
if (mIndentLines != lines) {
mIndentLines = lines;
// Invalidate layout.
- setHint(getHint());
+ nullLayouts();
+ requestLayout();
return true;
}
return false;
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 4104b6ca9d..15b2718 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -276,9 +276,16 @@
boolean hasNormal = false;
for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
View child = mMessageContainer.getChildAt(i);
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
if (child instanceof MessagingLinearLayout.MessagingChild) {
int type = ((MessagingLinearLayout.MessagingChild) child).getMeasuredType();
- if (type == MEASURED_TOO_SMALL) {
+ boolean tooSmall = type == MEASURED_TOO_SMALL;
+ final MessagingLinearLayout.LayoutParams lp =
+ (MessagingLinearLayout.LayoutParams) child.getLayoutParams();
+ tooSmall |= lp.hide;
+ if (tooSmall) {
if (hasNormal) {
return MEASURED_SHORTENED;
} else {
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 99d9839..c15b7ee 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -205,37 +205,8 @@
return 0;
}
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
- jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
- jboolean useBpfStats) {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- return -1;
- }
-
- std::vector<std::string> limitIfaces;
- if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
- int num = env->GetArrayLength(limitIfacesObj);
- for (int i = 0; i < num; i++) {
- jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
- ScopedUtfChars string8(env, string);
- if (string8.c_str() != NULL) {
- limitIfaces.push_back(std::string(string8.c_str()));
- }
- }
- }
- std::vector<stats_line> lines;
-
-
- if (useBpfStats) {
- if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
- return -1;
- } else {
- if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
- limitUid, path8.c_str()) < 0)
- return -1;
- }
-
+static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats,
+ std::vector<stats_line>& lines) {
int size = lines.size();
bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
@@ -308,14 +279,58 @@
env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
}
-
return 0;
}
+static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
+ jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
+ jboolean useBpfStats) {
+ ScopedUtfChars path8(env, path);
+ if (path8.c_str() == NULL) {
+ return -1;
+ }
+
+ std::vector<std::string> limitIfaces;
+ if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
+ int num = env->GetArrayLength(limitIfacesObj);
+ for (int i = 0; i < num; i++) {
+ jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
+ ScopedUtfChars string8(env, string);
+ if (string8.c_str() != NULL) {
+ limitIfaces.push_back(std::string(string8.c_str()));
+ }
+ }
+ }
+ std::vector<stats_line> lines;
+
+
+ if (useBpfStats) {
+ if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
+ return -1;
+ } else {
+ if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
+ limitUid, path8.c_str()) < 0)
+ return -1;
+ }
+
+ return statsLinesToNetworkStats(env, clazz, stats, lines);
+}
+
+static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) {
+ std::vector<stats_line> lines;
+
+ if (parseBpfNetworkStatsDev(&lines) < 0)
+ return -1;
+
+ return statsLinesToNetworkStats(env, clazz, stats, lines);
+}
+
static const JNINativeMethod gMethods[] = {
{ "nativeReadNetworkStatsDetail",
"(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
- (void*) readNetworkStatsDetail }
+ (void*) readNetworkStatsDetail },
+ { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
+ (void*) readNetworkStatsDev },
};
int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) {
diff --git a/core/proto/android/app/notification_channel.proto b/core/proto/android/app/notification_channel.proto
index 337aa1c..d3808e8 100644
--- a/core/proto/android/app/notification_channel.proto
+++ b/core/proto/android/app/notification_channel.proto
@@ -53,4 +53,5 @@
optional android.media.AudioAttributesProto audio_attributes = 16;
// If this is a blockable system notification channel.
optional bool is_blockable_system = 17;
+ optional bool fg_service_shown = 18;
}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 503bd21..64e1239 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -161,6 +161,7 @@
optional CpuFreqProto cpu_freq = 2004 [
(section).type = SECTION_FILE,
+ (section).device_specific = true,
(section).args = "/sys/devices/system/cpu/cpufreq/all_time_in_state"
];
@@ -170,7 +171,8 @@
];
optional BatteryTypeProto battery_type = 2006 [
- (section).type = SECTION_NONE, // disabled since the path is device specific!
+ (section).type = SECTION_FILE,
+ (section).device_specific = true,
(section).args = "/sys/class/power_supply/bms/battery_type"
];
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 92560f3..1f8d43c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -840,6 +840,77 @@
android:protectionLevel="dangerous|instant" />
<!-- ====================================================================== -->
+ <!-- Permissions for accessing the call log -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated telephony features. -->
+ <permission-group android:name="android.permission-group.CALL_LOG"
+ android:icon="@drawable/perm_group_phone_calls"
+ android:label="@string/permgrouplab_calllog"
+ android:description="@string/permgroupdesc_calllog"
+ android:request="@string/permgrouprequest_calllog"
+ android:priority="450" />
+
+ <!-- Allows an application to access the IMS call service: making and
+ modifying a call
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
+ android:label="@string/permlab_accessImsCallService"
+ android:description="@string/permdesc_accessImsCallService"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to read the user's call log.
+ <p class="note"><strong>Note:</strong> If your app uses the
+ {@link #READ_CONTACTS} permission and <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 16 or higher.</p>
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.READ_CALL_LOG"
+ android:permissionGroup="android.permission-group.CALL_LOG"
+ android:label="@string/permlab_readCallLog"
+ android:description="@string/permdesc_readCallLog"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to write (but not read) the user's
+ call log data.
+ <p class="note"><strong>Note:</strong> If your app uses the
+ {@link #WRITE_CONTACTS} permission and <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 16 or higher.</p>
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.WRITE_CALL_LOG"
+ android:permissionGroup="android.permission-group.CALL_LOG"
+ android:label="@string/permlab_writeCallLog"
+ android:description="@string/permdesc_writeCallLog"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to see the number being dialed during an outgoing
+ call with the option to redirect the call to a different number or
+ abort the call altogether.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
+ android:permissionGroup="android.permission-group.CALL_LOG"
+ android:label="@string/permlab_processOutgoingCalls"
+ android:description="@string/permdesc_processOutgoingCalls"
+ android:protectionLevel="dangerous" />
+
+ <!-- ====================================================================== -->
<!-- Permissions for accessing the device telephony -->
<!-- ====================================================================== -->
<eat-comment />
@@ -891,54 +962,6 @@
android:description="@string/permdesc_callPhone"
android:protectionLevel="dangerous" />
- <!-- Allows an application to access the IMS call service: making and
- modifying a call
- <p>Protection level: signature|privileged
- @hide
- -->
- <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_accessImsCallService"
- android:description="@string/permdesc_accessImsCallService"
- android:protectionLevel="signature|privileged" />
-
- <!-- Allows an application to read the user's call log.
- <p class="note"><strong>Note:</strong> If your app uses the
- {@link #READ_CONTACTS} permission and <em>both</em> your <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
- minSdkVersion}</a> and <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
- grants your app this permission. If you don't need this permission, be sure your <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> is 16 or higher.</p>
- <p>Protection level: dangerous
- -->
- <permission android:name="android.permission.READ_CALL_LOG"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readCallLog"
- android:description="@string/permdesc_readCallLog"
- android:protectionLevel="dangerous" />
-
- <!-- Allows an application to write (but not read) the user's
- call log data.
- <p class="note"><strong>Note:</strong> If your app uses the
- {@link #WRITE_CONTACTS} permission and <em>both</em> your <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
- minSdkVersion}</a> and <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
- grants your app this permission. If you don't need this permission, be sure your <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> is 16 or higher.</p>
- <p>Protection level: dangerous
- -->
- <permission android:name="android.permission.WRITE_CALL_LOG"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_writeCallLog"
- android:description="@string/permdesc_writeCallLog"
- android:protectionLevel="dangerous" />
-
<!-- Allows an application to add voicemails into the system.
<p>Protection level: dangerous
-->
@@ -957,18 +980,6 @@
android:label="@string/permlab_use_sip"
android:protectionLevel="dangerous"/>
- <!-- Allows an application to see the number being dialed during an outgoing
- call with the option to redirect the call to a different number or
- abort the call altogether.
- <p>Protection level: dangerous
- -->
- <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_processOutgoingCalls"
- android:description="@string/permdesc_processOutgoingCalls"
- android:protectionLevel="dangerous" />
-
-
<!-- Allows the app to answer an incoming phone call.
<p>Protection level: dangerous
-->
diff --git a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml
new file mode 100644
index 0000000..6f3dc8c
--- /dev/null
+++ b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<!-- This should be kept in sync with task_open_enter.xml -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" android:zAdjustment="top">
+
+ <alpha
+ android:fromAlpha="1"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="67"
+ android:duration="217"/>
+
+ <translate
+ android:fromXDelta="-105%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/aggressive_ease"
+ android:startOffset="50"
+ android:duration="383"/>
+
+ <scale
+ android:fromXScale="1.0526"
+ android:toXScale="1"
+ android:fromYScale="1.0526"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="283"/>
+
+ <scale
+ android:fromXScale="0.95"
+ android:toXScale="1"
+ android:fromYScale="0.95"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:startOffset="283"
+ android:duration="317"/>
+
+ <!-- To keep the thumbnail around longer and fade out the thumbnail -->
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:startOffset="717"
+ android:duration="200"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
index 6f3dc8c..4c2559f 100644
--- a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
+++ b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
@@ -31,7 +31,7 @@
android:duration="217"/>
<translate
- android:fromXDelta="-105%"
+ android:fromXDelta="105%"
android:toXDelta="0"
android:fillEnabled="true"
android:fillBefore="true"
diff --git a/core/res/res/layout/magnifier.xml b/core/res/res/layout/magnifier.xml
deleted file mode 100644
index f3344c7..0000000
--- a/core/res/res/layout/magnifier.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/magnifier_inner"
- android:layout_width="@android:dimen/magnifier_width"
- android:layout_height="@android:dimen/magnifier_height"
- android:elevation="@android:dimen/magnifier_elevation"
- android:background="?android:attr/floatingToolbarPopupBackgroundDrawable"
- android:scaleType="fitXY">
- <ImageView
- android:id="@+id/magnifier_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </LinearLayout>
-</LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index d1861d9..26eb4e7 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -24,7 +24,7 @@
>
<include layout="@layout/notification_template_header" />
- <LinearLayout
+ <com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_action_list_margin_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -34,7 +34,7 @@
android:clipToPadding="false"
android:orientation="vertical">
- <LinearLayout
+ <com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -62,7 +62,7 @@
android:visibility="gone"
android:textAlignment="viewStart"
/>
- </LinearLayout>
+ </com.android.internal.widget.RemeasuringLinearLayout>
<ViewStub android:layout="@layout/notification_material_reply_text"
android:id="@+id/notification_material_reply_container"
@@ -75,6 +75,6 @@
android:layout_marginEnd="@dimen/notification_content_margin_end"
android:layout_marginTop="@dimen/notification_content_margin" />
<include layout="@layout/notification_material_action_list" />
- </LinearLayout>
+ </com.android.internal.widget.RemeasuringLinearLayout>
<include layout="@layout/notification_template_right_icon" />
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index 08f8f57..0717d96 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -36,6 +36,7 @@
android:id="@+id/message_name"
style="@style/Widget.Material.Notification.MessagingName"
android:layout_width="wrap_content"
+ android:textAlignment="viewStart"
/>
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/group_message_container"
diff --git a/core/res/res/layout/notification_template_messaging_text_message.xml b/core/res/res/layout/notification_template_messaging_text_message.xml
index e728e69..3611186 100644
--- a/core/res/res/layout/notification_template_messaging_text_message.xml
+++ b/core/res/res/layout/notification_template_messaging_text_message.xml
@@ -17,5 +17,6 @@
<com.android.internal.widget.MessagingTextMessage
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/message_text"
+ android:textAlignment="viewStart"
style="@style/Widget.Material.Notification.MessagingText"
/>
diff --git a/core/res/res/values-mcc405/config.xml b/core/res/res/values-mcc405/config.xml
index 6b77e9c..4cadef7 100644
--- a/core/res/res/values-mcc405/config.xml
+++ b/core/res/res/values-mcc405/config.xml
@@ -20,4 +20,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Whether camera shutter sound is forced or not (country specific). -->
<bool name="config_camera_sound_forced">true</bool>
+ <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+ <bool name="config_showAreaUpdateInfoSettings">true</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c7b65ef..791f7c6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -247,7 +247,7 @@
<dimen name="notification_header_shrink_min_width">72dp</dimen>
<!-- The minimum height of the content if there are at least two lines or a picture-->
- <dimen name="notification_min_content_height">41dp</dimen>
+ <dimen name="notification_min_content_height">39dp</dimen>
<!-- The size of the media actions in the media notification. -->
<dimen name="media_notification_action_button_size">48dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b92052b..bf7ca52 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -724,6 +724,14 @@
<b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to take pictures and record video?</string>
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgrouplab_calllog">Call logs</string>
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgroupdesc_calllog">read and write phone call log</string>
+ <!-- Message shown to the user when the apps requests permission from this group -->
+ <string name="permgrouprequest_calllog">Allow
+ <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to access your phone call logs?</string>
+
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgrouplab_phone">Phone</string>
<!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgroupdesc_phone">make and manage phone calls</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c3ab1a6..5edafec 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2587,9 +2587,6 @@
<java-symbol type="attr" name="floatingToolbarDividerColor" />
<!-- Magnifier -->
- <java-symbol type="id" name="magnifier_image" />
- <java-symbol type="id" name="magnifier_inner" />
- <java-symbol type="layout" name="magnifier" />
<java-symbol type="dimen" name="magnifier_width" />
<java-symbol type="dimen" name="magnifier_height" />
<java-symbol type="dimen" name="magnifier_elevation" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 9ef58ab..1750dac 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -16,7 +16,11 @@
package android.app.activity;
+import static android.content.Intent.ACTION_EDIT;
+import static android.content.Intent.ACTION_VIEW;
+
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.ActivityThread;
@@ -27,6 +31,7 @@
import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.StopActivityItem;
import android.content.Intent;
+import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
@@ -94,6 +99,36 @@
});
}
+ /** Verify that custom intent set via Activity#setIntent() is preserved on relaunch. */
+ @Test
+ public void testCustomIntentPreservedOnRelaunch() throws Exception {
+ final Intent initIntent = new Intent();
+ initIntent.setAction(ACTION_VIEW);
+ final Activity activity = mActivityTestRule.launchActivity(initIntent);
+ IBinder token = activity.getActivityToken();
+
+ final ActivityThread activityThread = activity.getActivityThread();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // Recreate and check that intent is still the same.
+ activity.recreate();
+
+ final Activity newActivity = activityThread.getActivity(token);
+ assertTrue("Original intent must be preserved after recreate",
+ initIntent.filterEquals(newActivity.getIntent()));
+
+ // Set custom intent, recreate and check if it is preserved.
+ final Intent customIntent = new Intent();
+ customIntent.setAction(ACTION_EDIT);
+ newActivity.setIntent(customIntent);
+
+ activity.recreate();
+
+ final Activity lastActivity = activityThread.getActivity(token);
+ assertTrue("Custom intent must be preserved after recreate",
+ customIntent.filterEquals(lastActivity.getIntent()));
+ });
+ }
+
private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
null, 0, new MergedConfiguration(), false /* preserveWindow */);
diff --git a/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java b/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
new file mode 100644
index 0000000..e21143d
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import static android.view.View.VISIBLE;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.test.InstrumentationRegistry;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+public class BackgroundFallbackTest {
+
+ private static final int NAVBAR_BOTTOM = 0;
+ private static final int NAVBAR_LEFT = 1;
+ private static final int NAVBAR_RIGHT = 2;
+
+ private static final int SCREEN_HEIGHT = 2000;
+ private static final int SCREEN_WIDTH = 1000;
+ private static final int STATUS_HEIGHT = 100;
+ private static final int NAV_SIZE = 200;
+
+ private static final boolean INSET_CONTENT_VIEWS = true;
+ private static final boolean DONT_INSET_CONTENT_VIEWS = false;
+
+ BackgroundFallback mFallback;
+ Drawable mDrawableMock;
+
+ ViewGroup mStatusBarView;
+ ViewGroup mNavigationBarView;
+
+ ViewGroup mDecorViewMock;
+ ViewGroup mContentRootMock;
+ ViewGroup mContentContainerMock;
+ ViewGroup mContentMock;
+
+ int mLastTop = 0;
+
+ @Before
+ public void setUp() throws Exception {
+ mFallback = new BackgroundFallback();
+ mDrawableMock = mock(Drawable.class);
+
+ mFallback.setDrawable(mDrawableMock);
+
+ }
+
+ @Test
+ public void hasFallback_withDrawable_true() {
+ mFallback.setDrawable(mDrawableMock);
+ assertThat(mFallback.hasFallback(), is(true));
+ }
+
+ @Test
+ public void hasFallback_withoutDrawable_false() {
+ mFallback.setDrawable(null);
+ assertThat(mFallback.hasFallback(), is(false));
+ }
+
+ @Test
+ public void draw_portrait_noFallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_BOTTOM);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_portrait_translucentBars_fallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_BOTTOM);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyFallbackTop(STATUS_HEIGHT);
+ verifyFallbackBottom(NAV_SIZE);
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_landscape_translucentBars_fallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_RIGHT);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyFallbackTop(STATUS_HEIGHT);
+ verifyFallbackRight(NAV_SIZE);
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_seascape_translucentBars_fallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_LEFT);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyFallbackTop(STATUS_HEIGHT);
+ verifyFallbackLeft(NAV_SIZE);
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_landscape_noFallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_RIGHT);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_seascape_noFallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_LEFT);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_seascape_translucentBars_noInsets_noFallback() {
+ setUpViewHierarchy(DONT_INSET_CONTENT_VIEWS, NAVBAR_LEFT);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ private void verifyFallbackTop(int size) {
+ verify(mDrawableMock).setBounds(0, 0, SCREEN_WIDTH, size);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ mLastTop = size;
+ }
+
+ private void verifyFallbackLeft(int size) {
+ verify(mDrawableMock).setBounds(0, mLastTop, size, SCREEN_HEIGHT);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ }
+
+ private void verifyFallbackRight(int size) {
+ verify(mDrawableMock).setBounds(SCREEN_WIDTH - size, mLastTop, SCREEN_WIDTH, SCREEN_HEIGHT);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ }
+
+ private void verifyFallbackBottom(int size) {
+ verify(mDrawableMock).setBounds(0, SCREEN_HEIGHT - size, SCREEN_WIDTH, SCREEN_HEIGHT);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ }
+
+ private void setUpViewHierarchy(boolean insetContentViews, int navBarPosition) {
+ int insetLeft = 0;
+ int insetTop = 0;
+ int insetRight = 0;
+ int insetBottom = 0;
+
+ mStatusBarView = mockView(0, 0, SCREEN_WIDTH, STATUS_HEIGHT,
+ new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetTop = STATUS_HEIGHT;
+ }
+
+ switch (navBarPosition) {
+ case NAVBAR_BOTTOM:
+ mNavigationBarView = mockView(0, SCREEN_HEIGHT - NAV_SIZE, SCREEN_WIDTH,
+ SCREEN_HEIGHT, new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetBottom = NAV_SIZE;
+ }
+ break;
+ case NAVBAR_LEFT:
+ mNavigationBarView = mockView(0, 0, NAV_SIZE, SCREEN_HEIGHT,
+ new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetLeft = NAV_SIZE;
+ }
+ break;
+ case NAVBAR_RIGHT:
+ mNavigationBarView = mockView(SCREEN_WIDTH - NAV_SIZE, 0, SCREEN_WIDTH,
+ SCREEN_HEIGHT, new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetRight = NAV_SIZE;
+ }
+ break;
+ }
+
+ mContentMock = mockView(0, 0, SCREEN_WIDTH - insetLeft - insetRight,
+ SCREEN_HEIGHT - insetTop - insetBottom, null, VISIBLE, emptyList());
+ mContentContainerMock = mockView(0, 0, SCREEN_WIDTH - insetLeft - insetRight,
+ SCREEN_HEIGHT - insetTop - insetBottom, null, VISIBLE, asList(mContentMock));
+ mContentRootMock = mockView(insetLeft, insetTop, SCREEN_WIDTH - insetRight,
+ SCREEN_HEIGHT - insetBottom, null, VISIBLE, asList(mContentContainerMock));
+
+ mDecorViewMock = mockView(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null, VISIBLE,
+ asList(mContentRootMock, mStatusBarView, mNavigationBarView));
+ }
+
+ private void setTranslucent(ViewGroup bar) {
+ bar.setBackground(new ColorDrawable(Color.TRANSPARENT));
+ }
+
+ private ViewGroup mockView(int left, int top, int right, int bottom, Drawable background,
+ int visibility, List<ViewGroup> children) {
+ final ViewGroup v = new FrameLayout(InstrumentationRegistry.getTargetContext());
+
+ v.layout(left, top, right, bottom);
+ v.setBackground(background);
+ v.setVisibility(visibility);
+
+ for (ViewGroup c : children) {
+ v.addView(c);
+ }
+
+ return v;
+ }
+}
\ No newline at end of file
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
index a7f4d4d..fd33133 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.cpp
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -57,7 +57,8 @@
int pxOffset = -(scrollPx % (mItemSpacing + mItemHeight));
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- mListView->stagingProperties().getWidth(), mListView->stagingProperties().getHeight()));
+ mListView->stagingProperties().getWidth(), mListView->stagingProperties().getHeight(),
+ mListView.get()));
for (size_t ci = 0; ci < mListItems.size(); ci++) {
// update item position
auto listItem = mListItems[(ci + itemIndexOffset) % mListItems.size()];
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 1bfa046..2752ae9 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -250,7 +250,8 @@
static void recordNode(RenderNode& node, std::function<void(Canvas&)> contentCallback) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- node.stagingProperties().getWidth(), node.stagingProperties().getHeight()));
+ node.stagingProperties().getWidth(), node.stagingProperties().getHeight(),
+ &node));
contentCallback(*canvas.get());
node.setStagingDisplayList(canvas->finishRecording());
}
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index 38999cb..f0a5e9d 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -44,7 +44,8 @@
std::unique_ptr<Canvas> canvas(
Canvas::create_recording_canvas(container->stagingProperties().getWidth(),
- container->stagingProperties().getHeight()));
+ container->stagingProperties().getHeight(),
+ container.get()));
Paint paint;
paint.setAntiAlias(true);
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp
index 003d8e9..a64e844 100644
--- a/libs/hwui/tests/common/scenes/TvApp.cpp
+++ b/libs/hwui/tests/common/scenes/TvApp.cpp
@@ -194,7 +194,8 @@
// re-recording card's canvas, not necessary but to add some burden to CPU
std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas(
- card->stagingProperties().getWidth(), card->stagingProperties().getHeight()));
+ card->stagingProperties().getWidth(), card->stagingProperties().getHeight(),
+ card.get()));
sp<RenderNode> image = mImages[ci];
sp<RenderNode> infoArea = mInfoAreas[ci];
cardcanvas->drawRenderNode(infoArea.get());
@@ -205,14 +206,16 @@
sp<RenderNode> overlay = mOverlays[ci];
std::unique_ptr<Canvas> canvas(
Canvas::create_recording_canvas(overlay->stagingProperties().getWidth(),
- overlay->stagingProperties().getHeight()));
+ overlay->stagingProperties().getHeight(),
+ overlay.get()));
canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver);
overlay->setStagingDisplayList(canvas->finishRecording());
cardcanvas->drawRenderNode(overlay.get());
} else {
// re-recording image node's canvas, animating ColorFilter
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- image->stagingProperties().getWidth(), image->stagingProperties().getHeight()));
+ image->stagingProperties().getWidth(), image->stagingProperties().getHeight(),
+ image.get()));
SkPaint paint;
sk_sp<SkColorFilter> filter(
SkColorFilter::MakeModeFilter((curFrame % 150) << 24, SkBlendMode::kSrcATop));
diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto
index b3ed393..e8280ed 100644
--- a/libs/incident/proto/android/section.proto
+++ b/libs/incident/proto/android/section.proto
@@ -51,6 +51,7 @@
message SectionFlags {
optional SectionType type = 1 [default = SECTION_NONE];
optional string args = 2;
+ optional bool device_specific = 3 [default = false];
}
extend google.protobuf.FieldOptions {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 1ca3c1d..cdaabdc 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -234,7 +234,9 @@
DeviceChooserActivity activity = mActivity;
if (activity != null) {
- activity.mDeviceListView.removeFooterView(activity.mLoadingIndicator);
+ if (activity.mDeviceListView != null) {
+ activity.mDeviceListView.removeFooterView(activity.mLoadingIndicator);
+ }
mActivity = null;
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 2a82fc9..0a720a5 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -38,6 +38,9 @@
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
@@ -360,14 +363,19 @@
@Override
protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
+ return getFileForDocId(docId, visible, true);
+ }
+
+ private File getFileForDocId(String docId, boolean visible, boolean mustExist)
+ throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
- return buildFile(root, docId, visible);
+ return buildFile(root, docId, visible, mustExist);
}
private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
- return Pair.create(root, buildFile(root, docId, visible));
+ return Pair.create(root, buildFile(root, docId, visible, true));
}
private RootInfo getRootFromDocId(String docId) throws FileNotFoundException {
@@ -385,7 +393,7 @@
return root;
}
- private File buildFile(RootInfo root, String docId, boolean visible)
+ private File buildFile(RootInfo root, String docId, boolean visible, boolean mustExist)
throws FileNotFoundException {
final int splitIndex = docId.indexOf(':', 1);
final String path = docId.substring(splitIndex + 1);
@@ -398,7 +406,7 @@
target.mkdirs();
}
target = new File(target, path);
- if (!target.exists()) {
+ if (mustExist && !target.exists()) {
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
}
return target;
@@ -410,6 +418,19 @@
}
@Override
+ protected void onDocIdChanged(String docId) {
+ try {
+ // Touch the visible path to ensure that any sdcardfs caches have
+ // been updated to reflect underlying changes on disk.
+ final File visiblePath = getFileForDocId(docId, true, false);
+ if (visiblePath != null) {
+ Os.access(visiblePath.getAbsolutePath(), OsConstants.F_OK);
+ }
+ } catch (FileNotFoundException | ErrnoException ignored) {
+ }
+ }
+
+ @Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
synchronized (mRootsLock) {
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index cfcecbc..59e5cfb 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -250,19 +250,6 @@
<item>Best Effort (Adaptive Bit Rate)</item>
</string-array>
- <!-- TODO: Enable for translation per b/73007419 -->
- <!-- Summaries for Bluetooth Audio Active Device status. [CHAR LIMIT=50]-->
- <string-array name="bluetooth_audio_active_device_summaries" translatable="false" >
- <!-- Status message when the device is not Active. -->
- <item></item>
- <!-- Status message when the device is Active for Media and Phone. -->
- <item>, active</item>
- <!-- Status message when the device is Active for Media only. -->
- <item>, active(media)</item>
- <!-- Status message when the device is Active for Phone only. -->
- <item>, active(phone)</item>
- </string-array>
-
<!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
<string-array name="select_logd_size_titles">
<item>Off</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 50c9b5c..a46c3e6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -566,7 +566,7 @@
<!-- UI debug setting: Trigger Bluetooth Audio LDAC Playback Quality Selection -->
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Codec: Playback Quality</string>
<!-- UI debug setting: Select Bluetooth Audio LDAC Codec: LDAC Playback Quality -->
- <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Trigger Bluetooth Audio LDAC Codec\u000ASelection: Playback Quality</string>
+ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Trigger Bluetooth Audio LDAC\u000ACodec Selection: Playback Quality</string>
<!-- [CHAR LIMIT=NONE] Label for displaying Bluetooth Audio Codec Parameters while streaming -->
<string name="bluetooth_select_a2dp_codec_streaming_label">Streaming: <xliff:g id="streaming_parameter">%1$s</xliff:g></string>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index 3193101..87983b9 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -20,39 +20,54 @@
<!-- This is a view that shows general status information in Keyguard. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/presentation"
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+ <!-- This is mostly keyguard_status_view.xml with minor modifications -->
<com.android.keyguard.KeyguardStatusView
android:id="@+id/clock"
android:orientation="vertical"
- android:layout_width="wrap_content"
+ android:layout_width="410dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:orientation="vertical"
- android:focusable="true">
- <TextClock
- android:id="@+id/clock_view"
- android:layout_width="wrap_content"
+ android:orientation="vertical">
+ <RelativeLayout
+ android:id="@+id/keyguard_clock_container"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big_thin"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:baselineAligned="true" />
-
- <include layout="@layout/keyguard_status_area" />
+ android:layout_gravity="center_horizontal|top">
+ <TextClock
+ android:id="@+id/clock_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:letterSpacing="0.03"
+ android:textColor="?attr/wallpaperTextColor"
+ android:singleLine="true"
+ style="@style/widget_big_thin"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format" />
+ <View
+ android:id="@+id/clock_separator"
+ android:layout_width="@dimen/widget_separator_width"
+ android:layout_height="@dimen/widget_separator_thickness"
+ android:layout_below="@id/clock_view"
+ android:background="#f00"
+ android:layout_centerHorizontal="true" />
+ <include layout="@layout/keyguard_status_area"
+ android:id="@+id/keyguard_status_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/clock_separator" />
+ </RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="10dip"
+ android:layout_marginTop="@dimen/widget_vertical_padding"
android:layout_gravity="center_horizontal"
android:src="@drawable/kg_security_lock_normal" />
</LinearLayout>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 712b6e5..d628ca8 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -77,7 +77,7 @@
<dimen name="password_char_padding">8dp</dimen>
<!-- The vertical margin between the date and the owner info. -->
- <dimen name="date_owner_info_margin">2dp</dimen>
+ <dimen name="date_owner_info_margin">4dp</dimen>
<!-- The translation for disappearing security views after having solved them. -->
<dimen name="disappear_y_translation">-32dp</dimen>
diff --git a/packages/SystemUI/res/layout/app_ops_info.xml b/packages/SystemUI/res/layout/app_ops_info.xml
index 74a4c6e..676301e 100644
--- a/packages/SystemUI/res/layout/app_ops_info.xml
+++ b/packages/SystemUI/res/layout/app_ops_info.xml
@@ -21,6 +21,8 @@
android:layout_height="wrap_content"
android:id="@+id/app_ops_info"
android:clickable="true"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@*android:dimen/notification_content_margin_start"
android:paddingEnd="@*android:dimen/notification_content_margin_end"
@@ -63,10 +65,10 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
- android:gravity="end" >
+ android:gravity="end"
+ android:orientation="horizontal">
<TextView
android:id="@+id/settings"
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 5a0e767..1be3375 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -16,6 +16,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/menu_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index b1cb6cf..095f181 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -17,10 +17,12 @@
<com.android.systemui.statusbar.NotificationInfo
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/notification_guts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:id="@+id/notification_guts"
android:clickable="true"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@*android:dimen/notification_content_margin_start"
android:paddingEnd="@*android:dimen/notification_content_margin_end"
@@ -33,8 +35,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_marginTop="2dp" >
+ android:clipToPadding="false">
<ImageView
android:id="@+id/pkgicon"
android:layout_width="@dimen/notification_guts_header_height"
@@ -74,16 +75,16 @@
android:layout_toEndOf="@id/pkg_group_divider" />
<ImageButton
android:id="@+id/info"
- android:src="@drawable/ic_info"
- android:tint="?android:attr/colorAccent"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="12dp"
- android:layout_marginEnd="-12dp"
+ android:layout_width="56dp"
+ android:layout_height="56dp"
+ android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- android:contentDescription="@string/notification_more_settings"
+ android:layout_marginEnd="-16dp"
android:background="@drawable/ripple_drawable"
- android:layout_alignParentEnd="true" />
+ android:contentDescription="@string/notification_more_settings"
+ android:padding="16dp"
+ android:src="@drawable/ic_info"
+ android:tint="?android:attr/colorAccent" />
</RelativeLayout>
<LinearLayout
@@ -91,7 +92,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
- android:layout_marginTop="@*android:dimen/notification_header_padding_top"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<!-- Channel Info Block -->
@@ -105,14 +107,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginBottom="6dp"
- style="@style/TextAppearance.NotificationInfo.Primary" />
+ style="@android:style/TextAppearance.Material.Notification.Title" />
<!-- Question prompt -->
<TextView
android:id="@+id/block_prompt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@style/TextAppearance.NotificationInfo.Secondary" />
+ style="@android:style/TextAppearance.Material.Notification" />
</LinearLayout>
<!-- Settings and Done buttons -->
@@ -139,12 +140,14 @@
android:text="@string/inline_stop_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button"/>
<TextView
android:id="@+id/minimize"
android:text="@string/inline_minimize_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button" />
<TextView
android:id="@+id/keep"
@@ -152,6 +155,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="-8dp"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button"/>
</LinearLayout>
</LinearLayout>
@@ -160,22 +164,24 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
- android:layout_marginTop="@*android:dimen/notification_header_padding_top"
+ android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:visibility="gone"
android:orientation="horizontal" >
<TextView
android:id="@+id/confirmation_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
android:text="@string/notification_channel_disabled"
style="@style/TextAppearance.NotificationInfo.Confirmation"/>
<TextView
android:id="@+id/undo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/inline_undo"
android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
android:layout_marginEnd="-8dp"
+ android:text="@string/inline_undo"
style="@style/TextAppearance.NotificationInfo.Button"/>
</RelativeLayout>
</com.android.systemui.statusbar.NotificationInfo>
diff --git a/packages/SystemUI/res/layout/qs_paged_page.xml b/packages/SystemUI/res/layout/qs_paged_page.xml
index 25b1a2b..07f0c83 100644
--- a/packages/SystemUI/res/layout/qs_paged_page.xml
+++ b/packages/SystemUI/res/layout/qs_paged_page.xml
@@ -20,7 +20,7 @@
android:id="@+id/tile_page"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingLeft="@dimen/notification_side_paddings"
- android:paddingRight="@dimen/notification_side_paddings"
+ android:paddingStart="@dimen/notification_side_paddings"
+ android:paddingEnd="@dimen/notification_side_paddings"
android:clipChildren="false"
android:clipToPadding="false" />
diff --git a/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml b/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml
deleted file mode 100644
index eff9b36..0000000
--- a/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
- Copyright 2018, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Extends Framelayout -->
-<com.android.systemui.statusbar.DndSuppressingNotificationsView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/hidden_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone">
- <TextView
- android:id="@+id/hidden_notifications"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="64dp"
- android:paddingTop="28dp"
- android:gravity="top|center_horizontal"
- android:textColor="?attr/wallpaperTextColor"
- android:textSize="16sp"
- android:text="@string/dnd_suppressing_shade_text"/>
-</com.android.systemui.statusbar.DndSuppressingNotificationsView>
diff --git a/packages/SystemUI/res/layout/status_bar_wifi_group.xml b/packages/SystemUI/res/layout/status_bar_wifi_group.xml
index 482f780..c419b90 100644
--- a/packages/SystemUI/res/layout/status_bar_wifi_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_wifi_group.xml
@@ -28,8 +28,8 @@
android:id="@+id/wifi_group"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:paddingStart="2dp"
android:gravity="center_vertical"
+ android:layout_marginStart="2.5dp"
>
<FrameLayout
android:id="@+id/inout_container"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index fd25c40..efcca63 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -95,7 +95,7 @@
<color name="notification_gear_color">#ff757575</color>
<!-- The "inside" of a notification, reached via longpress -->
- <color name="notification_guts_bg_color">#eeeeee</color>
+ <color name="notification_guts_bg_color">#f8f9fa</color>
<color name="assist_orb_color">#ffffff</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index eb71911..af343fb 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -158,8 +158,17 @@
<!-- The space around a notification menu item -->
<dimen name="notification_menu_icon_padding">20dp</dimen>
- <!-- The veritical space around the buttons in the inline settings -->
- <dimen name="notification_guts_button_spacing">20dp</dimen>
+ <!-- The vertical space around the buttons in the inline settings -->
+ <dimen name="notification_guts_button_spacing">6dp</dimen>
+
+ <!-- The vertical padding a notification guts button has to fulfill the 48dp touch target -->
+ <dimen name="notification_guts_button_vertical_padding">14dp</dimen>
+
+ <!-- The horizontal padding for notification guts buttons-->
+ <dimen name="notification_guts_button_horizontal_padding">14dp</dimen>
+
+ <!-- The horizontal space around the buttons in the inline settings -->
+ <dimen name="notification_guts_button_horizontal_spacing">8dp</dimen>
<!-- The height of the header in inline settings -->
<dimen name="notification_guts_header_height">24dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1b4b15e..f1f80c7 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1064,7 +1064,7 @@
<string name="manage_notifications_text">Manage notifications</string>
<!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
- <string name="dnd_suppressing_shade_text">Notifications hidden by Do Not Disturb</string>
+ <string name="dnd_suppressing_shade_text">Do Not Disturb is hiding notifications</string>
<!-- Media projection permission dialog action text. [CHAR LIMIT=60] -->
<string name="media_projection_action_text">Start now</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 1e19534..c9b14dc 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -320,7 +320,7 @@
<item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
<item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
<item name="android:colorError">@*android:color/error_color_material_light</item>
- <item name="android:colorControlHighlight">@*android:color/primary_text_material_light</item>
+ <item name="android:colorControlHighlight">#40000000</item>
<item name="passwordStyle">@style/PasswordTheme.Light</item>
</style>
@@ -483,8 +483,10 @@
<item name="android:background">@drawable/btn_borderless_rect</item>
<item name="android:gravity">center</item>
<item name="android:focusable">true</item>
- <item name="android:paddingStart">8dp</item>
- <item name="android:paddingEnd">8dp</item>
+ <item name="android:paddingTop">@dimen/notification_guts_button_vertical_padding</item>
+ <item name="android:paddingBottom">@dimen/notification_guts_button_vertical_padding</item>
+ <item name="android:paddingLeft">@dimen/notification_guts_button_horizontal_padding</item>
+ <item name="android:paddingRight">@dimen/notification_guts_button_horizontal_padding</item>
</style>
<style name="TextAppearance.HeadsUpStatusBarText"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/MetricsLoggerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/MetricsLoggerCompat.java
index e93e78d..952c8ae 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/MetricsLoggerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/MetricsLoggerCompat.java
@@ -17,10 +17,12 @@
package com.android.systemui.shared.system;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
public class MetricsLoggerCompat {
private final MetricsLogger mMetricsLogger;
+ public static final int OVERVIEW_ACTIVITY = MetricsEvent.OVERVIEW_ACTIVITY;
public MetricsLoggerCompat() {
mMetricsLogger = new MetricsLogger();
@@ -37,4 +39,12 @@
public void visible(int category) {
mMetricsLogger.visible(category);
}
+
+ public void hidden(int category) {
+ mMetricsLogger.hidden(category);
+ }
+
+ public void visibility(int category, boolean visible) {
+ mMetricsLogger.visibility(category, visible);
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TonalCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TonalCompat.java
new file mode 100644
index 0000000..4a0f89b
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TonalCompat.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shared.system;
+
+import android.app.WallpaperColors;
+import android.content.Context;
+
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
+import com.android.internal.colorextraction.types.Tonal;
+
+public class TonalCompat {
+
+ private final Tonal mTonal;
+
+ public TonalCompat(Context context) {
+ mTonal = new Tonal(context);
+ }
+
+ public ExtractionInfo extractDarkColors(WallpaperColors colors) {
+ GradientColors darkColors = new GradientColors();
+ mTonal.extractInto(colors, new GradientColors(), darkColors, new GradientColors());
+
+ ExtractionInfo result = new ExtractionInfo();
+ result.mainColor = darkColors.getMainColor();
+ result.secondaryColor = darkColors.getSecondaryColor();
+ result.supportsDarkText = darkColors.supportsDarkText();
+ if (colors != null) {
+ result.supportsDarkTheme =
+ (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
+ }
+ return result;
+ }
+
+ public static class ExtractionInfo {
+ public int mainColor;
+ public int secondaryColor;
+ public boolean supportsDarkText;
+ public boolean supportsDarkTheme;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index c31cea2..33cac3b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -145,17 +145,13 @@
}
private void showSlice() {
- if (mPulsing) {
+ if (mPulsing || mSlice == null) {
mTitle.setVisibility(GONE);
mRow.setVisibility(GONE);
mContentChangeListener.accept(getLayoutTransition() != null);
return;
}
- if (mSlice == null) {
- return;
- }
-
ListContent lc = new ListContent(getContext(), mSlice);
mHasHeader = lc.hasHeader();
List<SliceItem> subItems = lc.getRowItems();
@@ -170,18 +166,6 @@
SliceItem mainTitle = header.getTitleItem();
CharSequence title = mainTitle != null ? mainTitle.getText() : null;
mTitle.setText(title);
-
- // Check if we're already ellipsizing the text.
- // We're going to figure out the best possible line break if not.
- Layout layout = mTitle.getLayout();
- if (layout != null){
- final int lineCount = layout.getLineCount();
- if (lineCount > 0) {
- if (layout.getEllipsisCount(lineCount - 1) == 0) {
- mTitle.setText(findBestLineBreak(title));
- }
- }
- }
}
mClickActions.clear();
@@ -385,6 +369,27 @@
mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size);
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ // Find best ellipsis strategy for the title.
+ // Done on onMeasure since TextView#getLayout needs a measure pass to calculate its bounds.
+ Layout layout = mTitle.getLayout();
+ if (layout != null) {
+ final int lineCount = layout.getLineCount();
+ if (lineCount > 0) {
+ if (layout.getEllipsisCount(lineCount - 1) == 0) {
+ CharSequence title = mTitle.getText();
+ CharSequence bestLineBreak = findBestLineBreak(title);
+ if (!TextUtils.equals(title, bestLineBreak)) {
+ mTitle.setText(bestLineBreak);
+ }
+ }
+ }
+ }
+ }
+
public static class Row extends LinearLayout {
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 727b62b..454528e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -164,7 +164,9 @@
protected void onFinishInflate() {
super.onFinishInflate();
mLogoutView = findViewById(R.id.logout);
- mLogoutView.setOnClickListener(this::onLogoutClicked);
+ if (mLogoutView != null) {
+ mLogoutView.setOnClickListener(this::onLogoutClicked);
+ }
mClockView = findViewById(R.id.clock_view);
mClockView.setShowCurrentUserTime(true);
@@ -296,6 +298,9 @@
}
public int getLogoutButtonHeight() {
+ if (mLogoutView == null) {
+ return 0;
+ }
return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
}
@@ -304,6 +309,9 @@
}
private void updateLogoutView() {
+ if (mLogoutView == null) {
+ return;
+ }
mLogoutView.setVisibility(shouldShowLogout() ? VISIBLE : GONE);
// Logout button will stay in language of user 0 if we don't set that manually.
mLogoutView.setText(mContext.getResources().getString(
@@ -390,7 +398,9 @@
private void updateDark() {
boolean dark = mDarkAmount == 1;
- mLogoutView.setAlpha(dark ? 0 : 1);
+ if (mLogoutView != null) {
+ mLogoutView.setAlpha(dark ? 0 : 1);
+ }
if (mOwnerInfo != null) {
boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
mOwnerInfo.setVisibility(hasText && mDarkAmount != 1 ? VISIBLE : GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 282a8f1..9307c22 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -66,6 +66,7 @@
public static final String TAG_OPS = "OverviewProxyService";
public static final boolean DEBUG_OVERVIEW_PROXY = false;
private static final long BACKOFF_MILLIS = 5000;
+ private static final long DEFERRED_CALLBACK_MILLIS = 5000;
private final Context mContext;
private final Handler mHandler;
@@ -162,6 +163,12 @@
}
};
+ private final Runnable mDeferredConnectionCallback = () -> {
+ Log.w(TAG_OPS, "Binder supposed established connection but actual connection to service "
+ + "timed out, trying again");
+ internalConnectToCurrentUser();
+ };
+
private final BroadcastReceiver mLauncherStateChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -181,22 +188,33 @@
private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- if (service != null) {
- mConnectionBackoffAttempts = 0;
- mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
- // Listen for launcher's death
- try {
- service.linkToDeath(mOverviewServiceDeathRcpt, 0);
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Lost connection to launcher service", e);
- }
- try {
- mOverviewProxy.onBind(mSysUiProxy);
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Failed to call onBind()", e);
- }
- notifyConnectionChanged();
+ mHandler.removeCallbacks(mDeferredConnectionCallback);
+ mConnectionBackoffAttempts = 0;
+ mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
+ // Listen for launcher's death
+ try {
+ service.linkToDeath(mOverviewServiceDeathRcpt, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG_OPS, "Lost connection to launcher service", e);
}
+ try {
+ mOverviewProxy.onBind(mSysUiProxy);
+ } catch (RemoteException e) {
+ Log.e(TAG_OPS, "Failed to call onBind()", e);
+ }
+ notifyConnectionChanged();
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ Log.w(TAG_OPS, "Null binding of '" + name + "', try reconnecting");
+ internalConnectToCurrentUser();
+ }
+
+ @Override
+ public void onBindingDied(ComponentName name) {
+ Log.w(TAG_OPS, "Binding died of '" + name + "', try reconnecting");
+ internalConnectToCurrentUser();
}
@Override
@@ -262,6 +280,9 @@
// If user has not setup yet or already connected, do not try to connect
if (!mDeviceProvisionedController.isCurrentUserSetup() || !isEnabled()) {
+ Log.v(TAG_OPS, "Cannot attempt connection, is setup "
+ + mDeviceProvisionedController.isCurrentUserSetup() + ", is enabled "
+ + isEnabled());
return;
}
mHandler.removeCallbacks(mConnectionRunnable);
@@ -275,11 +296,16 @@
} catch (SecurityException e) {
Log.e(TAG_OPS, "Unable to bind because of security error", e);
}
- if (!bound) {
+ if (bound) {
+ // Ensure that connection has been established even if it thinks it is bound
+ mHandler.postDelayed(mDeferredConnectionCallback, DEFERRED_CALLBACK_MILLIS);
+ } else {
// Retry after exponential backoff timeout
final long timeoutMs = (long) Math.scalb(BACKOFF_MILLIS, mConnectionBackoffAttempts);
mHandler.postDelayed(mConnectionRunnable, timeoutMs);
mConnectionBackoffAttempts++;
+ Log.w(TAG_OPS, "Failed to connect on attempt " + mConnectionBackoffAttempts
+ + " will try again in " + timeoutMs + "ms");
}
}
@@ -351,6 +377,10 @@
pw.print(" isCurrentUserSetup="); pw.println(mDeviceProvisionedController
.isCurrentUserSetup());
pw.print(" isConnected="); pw.println(mOverviewProxy != null);
+ pw.print(" mRecentsComponentName="); pw.println(mRecentsComponentName);
+ pw.print(" mIsEnabled="); pw.println(isEnabled());
+ pw.print(" mInteractionFlags="); pw.println(mInteractionFlags);
+ pw.print(" mQuickStepIntent="); pw.println(mQuickStepIntent);
}
public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index f595d77..a7163bb 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -94,6 +94,8 @@
String OVERVIEW_OPENED_FROM_HOME_COUNT = "OverviewOpenedFromHomeCount";
String HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING = "HasSeenRecentsSwipeUpOnboarding";
String HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING = "HasSeenRecentsQuickScrubOnboarding";
+ String HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE =
+ "HasDismissedRecentsQuickScrubOnboardingOnce";
String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount";
String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed";
String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData";
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 087d481..ea3f95e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -344,8 +344,8 @@
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
- if (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0
+ if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, getCurrentUser().id) != 0
&& shouldDisplayLockdown()) {
mItems.add(getLockdownAction());
mHasLockdownButton = true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 6d46e85..45d63e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -93,7 +93,8 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int numTiles = mRecords.size();
- final int width = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
+ final int width = MeasureSpec.getSize(widthMeasureSpec)
+ - getPaddingStart() - getPaddingEnd();
final int numRows = (numTiles + mColumns - 1) / mColumns;
mCellWidth = (width - mSidePadding * 2 - (mCellMarginHorizontal * mColumns)) / mColumns;
@@ -140,16 +141,8 @@
final TileRecord record = mRecords.get(i);
final int top = getRowTop(row);
- final int right;
- final int left;
- if (isRtl) {
- right = w - getColumnStart(column);
- left = right - mCellWidth;
- } else {
- left = getColumnStart(column);
- right = left + mCellWidth;
- }
-
+ final int left = getColumnStart(isRtl ? mColumns - column - 1 : column);
+ final int right = left + mCellWidth;
record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
}
}
@@ -159,6 +152,7 @@
}
private int getColumnStart(int column) {
- return column * (mCellWidth + mCellMarginHorizontal) + mCellMarginHorizontal + mPaddingLeft;
+ return getPaddingStart() + mSidePadding + mCellMarginHorizontal / 2 +
+ column * (mCellWidth + mCellMarginHorizontal);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 441d29b..5adeec3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -67,6 +67,10 @@
private static final long EDIT_ID = 10000;
private static final long DIVIDER_ID = 20000;
+ private static final int ACTION_NONE = 0;
+ private static final int ACTION_ADD = 1;
+ private static final int ACTION_MOVE = 2;
+
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -82,7 +86,7 @@
private List<TileInfo> mAllTiles;
private Holder mCurrentDrag;
- private boolean mAccessibilityMoving;
+ private int mAccessibilityAction = ACTION_NONE;
private int mAccessibilityFromIndex;
private QSTileHost mHost;
@@ -172,7 +176,7 @@
@Override
public int getItemViewType(int position) {
- if (mAccessibilityMoving && position == mEditIndex - 1) {
+ if (mAccessibilityAction == ACTION_ADD && position == mEditIndex - 1) {
return TYPE_ACCESSIBLE_DROP;
}
if (position == mTileDividerIndex) {
@@ -266,18 +270,18 @@
if (position > mEditIndex) {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_add_tile_label, info.state.label);
- } else if (mAccessibilityMoving) {
+ } else if (mAccessibilityAction != ACTION_NONE) {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_position_label, position + 1);
} else {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_tile_label, position + 1, info.state.label);
}
- holder.mTileView.onStateChanged(info.state);
+ holder.mTileView.handleStateChanged(info.state);
holder.mTileView.setShowAppLabel(position > mEditIndex && !info.isSystem);
if (mAccessibilityManager.isTouchExplorationEnabled()) {
- final boolean selectable = !mAccessibilityMoving || position < mEditIndex;
+ final boolean selectable = mAccessibilityAction == ACTION_NONE || position < mEditIndex;
holder.mTileView.setClickable(selectable);
holder.mTileView.setFocusable(selectable);
holder.mTileView.setImportantForAccessibility(selectable
@@ -288,13 +292,13 @@
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
- if (mAccessibilityMoving) {
+ if (mAccessibilityAction != ACTION_NONE) {
selectPosition(position, v);
} else {
if (position < mEditIndex && canRemoveTiles()) {
showAccessibilityDialog(position, v);
} else {
- startAccessibleDrag(position);
+ startAccessibleAdd(position);
}
}
}
@@ -302,21 +306,21 @@
}
}
}
-
+
private boolean canRemoveTiles() {
return mCurrentSpecs.size() > MIN_NUM_TILES;
}
private void selectPosition(int position, View v) {
- // Remove the placeholder.
- mAccessibilityMoving = false;
- mTiles.remove(mEditIndex--);
- notifyItemRemoved(mEditIndex - 1);
- // Don't remove items when the last position is selected.
- if (position == mEditIndex) position--;
-
+ if (mAccessibilityAction == ACTION_ADD) {
+ // Remove the placeholder.
+ mTiles.remove(mEditIndex--);
+ notifyItemRemoved(mEditIndex);
+ // Don't remove items when the last position is selected.
+ if (position == mEditIndex - 1) position--;
+ }
+ mAccessibilityAction = ACTION_NONE;
move(mAccessibilityFromIndex, position, v);
-
notifyDataSetChanged();
}
@@ -331,7 +335,7 @@
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
- startAccessibleDrag(position);
+ startAccessibleMove(position);
} else {
move(position, info.isSystem ? mEditIndex : mTileDividerIndex, v);
notifyItemChanged(mTileDividerIndex);
@@ -345,12 +349,18 @@
dialog.show();
}
- private void startAccessibleDrag(int position) {
- mAccessibilityMoving = true;
- mNeedsFocus = true;
+ private void startAccessibleAdd(int position) {
mAccessibilityFromIndex = position;
+ mAccessibilityAction = ACTION_ADD;
// Add placeholder for last slot.
mTiles.add(mEditIndex++, null);
+ mNeedsFocus = true;
+ notifyDataSetChanged();
+ }
+
+ private void startAccessibleMove(int position) {
+ mAccessibilityFromIndex = position;
+ mAccessibilityAction = ACTION_MOVE;
notifyDataSetChanged();
}
@@ -365,30 +375,26 @@
CharSequence fromLabel = mTiles.get(from).state.label;
move(from, to, mTiles);
updateDividerLocations();
- CharSequence announcement;
if (to >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE,
from);
- announcement = mContext.getString(R.string.accessibility_qs_edit_tile_removed,
- fromLabel);
} else if (from >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD,
to);
- announcement = mContext.getString(R.string.accessibility_qs_edit_tile_added,
- fromLabel, (to + 1));
+ v.announceForAccessibility(mContext.getString(R.string.accessibility_qs_edit_tile_added,
+ fromLabel, (to + 1)));
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_MOVE_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_MOVE,
to);
- announcement = mContext.getString(R.string.accessibility_qs_edit_tile_moved,
- fromLabel, (to + 1));
+ v.announceForAccessibility(mContext.getString(R.string.accessibility_qs_edit_tile_moved,
+ fromLabel, (to + 1)));
}
- v.announceForAccessibility(announcement);
saveSpecs(mHost);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 63be4b7..c7191f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -45,8 +45,8 @@
* Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the
* nearest hour and add on the AM/PM indicator.
*/
- private static final String HOUR_MINUTE_DATE_TIME_PATTERN = "h a";
- private static final String APPROXIMATE_HOUR_DATE_TIME_PATTERN = "h:m a";
+ private static final String PATTERN_HOUR = "h a";
+ private static final String PATTERN_HOUR_MINUTE = "h:mm a";
private ColorDisplayController mController;
@@ -142,9 +142,7 @@
// Choose between just showing the hour or also showing the minutes (based on the
// user-selected toggle time). This helps reduce how much space the label takes.
toggleTimeFormat = DateTimeFormatter.ofPattern(
- toggleTime.getMinute() == 0
- ? HOUR_MINUTE_DATE_TIME_PATTERN
- : APPROXIMATE_HOUR_DATE_TIME_PATTERN);
+ toggleTime.getMinute() == 0 ? PATTERN_HOUR : PATTERN_HOUR_MINUTE);
return mContext.getString(toggleTimeStringRes, toggleTime.format(toggleTimeFormat));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index ffa1444..31933d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
@@ -66,7 +67,7 @@
private static final String TAG = "RecentsOnboarding";
private static final boolean RESET_PREFS_FOR_DEBUG = false;
- private static final boolean ONBOARDING_ENABLED = false;
+ private static final boolean ONBOARDING_ENABLED = true;
private static final long SHOW_DELAY_MS = 500;
private static final long SHOW_HIDE_DURATION_MS = 300;
// Show swipe-up tips after opening overview from home this number of times.
@@ -76,9 +77,6 @@
// After explicitly dismissing, show again after launching this number of apps for swipe-up
// tips.
private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 5;
- // After explicitly dismissing, show again after launching this number of apps for QuickScrub
- // tips.
- private static final int QUICK_SCRUB_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 10;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -99,7 +97,7 @@
private boolean mHasDismissedSwipeUpTip;
private boolean mHasDismissedQuickScrubTip;
private int mNumAppsLaunchedSinceSwipeUpTipDismiss;
- private int mNumAppsLaunchedSinceQuickScrubTipDismiss;
+ private int mOverviewOpenedCountSinceQuickScrubTipDismiss;
private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
@Override
@@ -145,10 +143,9 @@
} else {
if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
if (mHasDismissedQuickScrubTip) {
- mNumAppsLaunchedSinceQuickScrubTipDismiss++;
- if (mNumAppsLaunchedSinceQuickScrubTipDismiss
- == QUICK_SCRUB_SHOW_ON_APP_LAUNCH_AFTER_DISMISS) {
- mNumAppsLaunchedSinceQuickScrubTipDismiss = 0;
+ if (mOverviewOpenedCountSinceQuickScrubTipDismiss
+ == QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+ mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
show(R.string.recents_quick_scrub_onboarding);
}
} else {
@@ -166,14 +163,19 @@
new OverviewProxyService.OverviewProxyListener() {
@Override
public void onOverviewShown(boolean fromHome) {
- boolean alreadySeenRecentsOnboarding = hasSeenSwipeUpOnboarding();
- if (!alreadySeenRecentsOnboarding && !fromHome) {
+ if (!hasSeenSwipeUpOnboarding() && !fromHome) {
setHasSeenSwipeUpOnboarding(true);
}
if (fromHome) {
setOpenedOverviewFromHomeCount(getOpenedOverviewFromHomeCount() + 1);
}
setOpenedOverviewCount(getOpenedOverviewCount() + 1);
+
+ if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+ if (mHasDismissedQuickScrubTip) {
+ mOverviewOpenedCountSinceQuickScrubTipDismiss++;
+ }
+ }
}
@Override
@@ -191,7 +193,11 @@
public void onViewAttachedToWindow(View view) {
if (view == mLayout) {
mLayoutAttachedToWindow = true;
- mHasDismissedSwipeUpTip = false;
+ if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) {
+ mHasDismissedSwipeUpTip = false;
+ } else {
+ mHasDismissedQuickScrubTip = false;
+ }
}
}
@@ -199,6 +205,17 @@
public void onViewDetachedFromWindow(View view) {
if (view == mLayout) {
mLayoutAttachedToWindow = false;
+ if (view.getTag().equals(R.string.recents_quick_scrub_onboarding)) {
+ mHasDismissedQuickScrubTip = true;
+ if (hasDismissedQuickScrubOnboardingOnce()) {
+ // If user dismisses the quick scrub tip twice, we consider user has seen it
+ // and do not show it again.
+ setHasSeenQuickScrubOnboarding(true);
+ } else {
+ setHasDismissedQuickScrubOnboardingOnce(true);
+ }
+ mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
+ }
}
}
};
@@ -228,15 +245,6 @@
if (v.getTag().equals(R.string.recents_swipe_up_onboarding)) {
mHasDismissedSwipeUpTip = true;
mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- } else {
- if (mHasDismissedQuickScrubTip) {
- // If user dismisses the quick scrub tip twice, we consider user has seen it
- // and do not show it again.
- setHasSeenQuickScrubOnboarding(true);
- } else {
- mHasDismissedQuickScrubTip = true;
- }
- mNumAppsLaunchedSinceQuickScrubTipDismiss = 0;
}
});
@@ -252,6 +260,7 @@
if (RESET_PREFS_FOR_DEBUG) {
setHasSeenSwipeUpOnboarding(false);
setHasSeenQuickScrubOnboarding(false);
+ setHasDismissedQuickScrubOnboardingOnce(false);
setOpenedOverviewCount(0);
setOpenedOverviewFromHomeCount(0);
}
@@ -289,7 +298,7 @@
mHasDismissedSwipeUpTip = false;
mHasDismissedQuickScrubTip = false;
mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- mNumAppsLaunchedSinceQuickScrubTipDismiss = 0;
+ mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
hide(false);
}
@@ -303,11 +312,15 @@
if (!shouldShow()) {
return;
}
+ if (mLayoutAttachedToWindow) {
+ hide(false);
+ }
mDismissView.setTag(stringRes);
+ mLayout.setTag(stringRes);
mTextView.setText(stringRes);
// Only show in portrait.
int orientation = mContext.getResources().getConfiguration().orientation;
- if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mWindowManager.addView(mLayout, getWindowLayoutParams());
@@ -348,11 +361,11 @@
.withLayer()
.setDuration(SHOW_HIDE_DURATION_MS)
.setInterpolator(new AccelerateInterpolator())
- .withEndAction(() -> mWindowManager.removeView(mLayout))
+ .withEndAction(() -> mWindowManager.removeViewImmediate(mLayout))
.start();
} else {
mLayout.animate().cancel();
- mWindowManager.removeView(mLayout);
+ mWindowManager.removeViewImmediate(mLayout);
}
}
}
@@ -400,6 +413,16 @@
}
}
+ private boolean hasDismissedQuickScrubOnboardingOnce() {
+ return Prefs.getBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE, false);
+ }
+
+ private void setHasDismissedQuickScrubOnboardingOnce(
+ boolean hasDismissedQuickScrubOnboardingOnce) {
+ Prefs.putBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE,
+ hasDismissedQuickScrubOnboardingOnce);
+ }
+
private int getOpenedOverviewFromHomeCount() {
return Prefs.getInt(mContext, OVERVIEW_OPENED_FROM_HOME_COUNT, 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 79fea9f..c8ee8735 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -376,15 +376,15 @@
public Rect getNonMinimizedSplitScreenSecondaryBounds() {
calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
+ mOtherTaskRect.bottom -= mStableInsets.bottom;
switch (mDockSide) {
case WindowManager.DOCKED_LEFT:
+ mOtherTaskRect.top += mStableInsets.top;
mOtherTaskRect.right -= mStableInsets.right;
break;
case WindowManager.DOCKED_RIGHT:
- mOtherTaskRect.left -= mStableInsets.left;
- break;
- case WindowManager.DOCKED_TOP:
- mOtherTaskRect.bottom -= mStableInsets.bottom;
+ mOtherTaskRect.top += mStableInsets.top;
+ mOtherTaskRect.left += mStableInsets.left;
break;
}
return mOtherTaskRect;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java
deleted file mode 100644
index db3a02d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.annotation.ColorInt;
-import android.annotation.DrawableRes;
-import android.annotation.IntegerRes;
-import android.annotation.StringRes;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.graphics.drawable.Icon;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.StackScrollState;
-
-public class DndSuppressingNotificationsView extends StackScrollerDecorView {
-
- private TextView mText;
- private @StringRes int mTextId = R.string.dnd_suppressing_shade_text;
-
- public DndSuppressingNotificationsView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- mText.setText(mTextId);
- }
-
- @Override
- protected View findContentView() {
- return findViewById(R.id.hidden_container);
- }
-
- @Override
- protected View findSecondaryView() {
- return null;
- }
-
- public void setColor(@ColorInt int color) {
- mText.setTextColor(color);
- }
-
- public void setOnContentClickListener(OnClickListener listener) {
- mText.setOnClickListener(listener);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mText = findViewById(R.id.hidden_notifications);
- }
-
- @Override
- public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
- return new DndSuppressingViewState();
- }
-
- public class DndSuppressingViewState extends ExpandableViewState {
- @Override
- public void applyToView(View view) {
- super.applyToView(view);
- if (view instanceof DndSuppressingNotificationsView) {
- DndSuppressingNotificationsView dndView = (DndSuppressingNotificationsView) view;
- boolean visible = this.clipTopAmount <= mText.getPaddingTop() * 0.6f;
- dndView.performVisibilityAnimation(visible && !dndView.willBeGone());
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3efeb6e..27fa48a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1635,6 +1635,7 @@
mTranslateableViews.get(i).setTranslationX(0);
}
invalidateOutline();
+ getEntry().expandedIcon.setScrollX(0);
}
mMenuRow.resetMenu();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b442bb4..419e262 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,6 +16,11 @@
package com.android.systemui.statusbar;
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
@@ -52,6 +57,7 @@
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -68,6 +74,7 @@
private final Environment mEnvironment;
private HeadsUpManager mHeadsUpManager;
+ final ZenModeController mZen = Dependency.get(ZenModeController.class);
final ForegroundServiceController mFsc = Dependency.get(ForegroundServiceController.class);
public static final class Entry {
@@ -474,6 +481,10 @@
}
protected boolean isExemptFromDndVisualSuppression(Entry entry) {
+ if (isNotificationBlockedByPolicy(entry.notification.getNotification())) {
+ return false;
+ }
+
if ((entry.notification.getNotification().flags
& Notification.FLAG_FOREGROUND_SERVICE) != 0) {
return true;
@@ -487,6 +498,26 @@
return false;
}
+ /**
+ * Categories that are explicitly called out on DND settings screens are always blocked, if
+ * DND has flagged them, even if they are foreground or system notifications that might
+ * otherwise visually bypass DND.
+ */
+ protected boolean isNotificationBlockedByPolicy(Notification n) {
+ if (isCategory(CATEGORY_CALL, n)
+ || isCategory(CATEGORY_MESSAGE, n)
+ || isCategory(CATEGORY_ALARM, n)
+ || isCategory(CATEGORY_EVENT, n)
+ || isCategory(CATEGORY_REMINDER, n)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isCategory(String category, Notification n) {
+ return Objects.equals(n.category, category);
+ }
+
public int getImportance(String key) {
if (mRankingMap != null) {
getRanking(key, mTmpRanking);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index bf94c1f..c3b4fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -191,6 +191,7 @@
}
private void updateState(WifiIconState state) {
+ setContentDescription(state.contentDescription);
if (mState.resId != state.resId && state.resId >= 0) {
NeutralGoodDrawable drawable = NeutralGoodDrawable
.create(mLightContext, mDarkContext, state.resId);
@@ -212,6 +213,7 @@
}
private void initViewState() {
+ setContentDescription(mState.contentDescription);
if (mState.resId >= 0) {
NeutralGoodDrawable drawable = NeutralGoodDrawable.create(
mLightContext, mDarkContext, mState.resId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 5768fa2..fc76f78e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -38,6 +38,8 @@
import androidx.car.widget.PagedListView;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.android.internal.util.UserIcons;
import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;
@@ -193,7 +195,10 @@
@Override
public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
UserRecord userRecord = mUsers.get(position);
- holder.mUserAvatarImageView.setImageBitmap(getUserRecordIcon(userRecord));
+ RoundedBitmapDrawable circleIcon = RoundedBitmapDrawableFactory.create(mRes,
+ getUserRecordIcon(userRecord));
+ circleIcon.setCircular(true);
+ holder.mUserAvatarImageView.setImageDrawable(circleIcon);
holder.mUserNameTextView.setText(userRecord.mInfo.name);
holder.mView.setOnClickListener(v -> {
if (userRecord == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index fc8ceb6..8ede224 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -530,6 +530,7 @@
protected void reset() {
mTransformedView = null;
+ mTransformInfo = null;
mSameAsAny = false;
mTransformationEndX = UNDEFINED;
mTransformationEndY = UNDEFINED;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 7284ee8..2161655 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -14,8 +14,12 @@
package com.android.systemui.statusbar.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.view.View;
+import com.android.systemui.Interpolators;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -26,6 +30,8 @@
* multiples of the same nav bar icon appearing.
*/
public class ButtonDispatcher {
+ private final static int FADE_DURATION_IN = 150;
+ private final static int FADE_DURATION_OUT = 100;
private final ArrayList<View> mViews = new ArrayList<>();
@@ -36,13 +42,24 @@
private View.OnLongClickListener mLongClickListener;
private View.OnHoverListener mOnHoverListener;
private Boolean mLongClickable;
- private Integer mAlpha;
+ private Float mAlpha;
private Float mDarkIntensity;
private Integer mVisibility = -1;
private Boolean mDelayTouchFeedback;
private KeyButtonDrawable mImageDrawable;
private View mCurrentView;
private boolean mVertical;
+ private ValueAnimator mFadeAnimator;
+
+ private final ValueAnimator.AnimatorUpdateListener mAlphaListener = animation ->
+ setAlpha((float) animation.getAnimatedValue());
+
+ private final AnimatorListenerAdapter mFadeListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setVisibility(getAlpha() == 1 ? View.VISIBLE : View.INVISIBLE);
+ }
+ };
public ButtonDispatcher(int id) {
mId = id;
@@ -64,19 +81,22 @@
if (mAlpha != null) {
view.setAlpha(mAlpha);
}
- if (mDarkIntensity != null) {
- ((ButtonInterface) view).setDarkIntensity(mDarkIntensity);
- }
- if (mVisibility != null) {
+ if (mVisibility != null && mVisibility != -1) {
view.setVisibility(mVisibility);
}
- if (mImageDrawable != null) {
- ((ButtonInterface) view).setImageDrawable(mImageDrawable);
+ if (view instanceof ButtonInterface) {
+ final ButtonInterface button = (ButtonInterface) view;
+ if (mDarkIntensity != null) {
+ button.setDarkIntensity(mDarkIntensity);
+ }
+ if (mImageDrawable != null) {
+ button.setImageDrawable(mImageDrawable);
+ }
+ if (mDelayTouchFeedback != null) {
+ button.setDelayTouchFeedback(mDelayTouchFeedback);
+ }
+ button.setVertical(mVertical);
}
- if (mDelayTouchFeedback != null) {
- ((ButtonInterface) view).setDelayTouchFeedback(mDelayTouchFeedback);
- }
- ((ButtonInterface) view).setVertical(mVertical);
}
public int getId() {
@@ -99,7 +119,9 @@
mImageDrawable = drawable;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
+ }
}
}
@@ -116,11 +138,13 @@
// This seems to be an instantaneous thing, so not going to persist it.
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).abortCurrentGesture();
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).abortCurrentGesture();
+ }
}
}
- public void setAlpha(int alpha) {
+ public void setAlpha(float alpha) {
mAlpha = alpha;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
@@ -132,7 +156,9 @@
mDarkIntensity = darkIntensity;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+ }
}
}
@@ -140,7 +166,9 @@
mDelayTouchFeedback = delay;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay);
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay);
+ }
}
}
@@ -192,6 +220,19 @@
}
}
+ public void animateFade(boolean in) {
+ if (mFadeAnimator != null) {
+ mFadeAnimator.cancel();
+ }
+ mFadeAnimator = ValueAnimator.ofFloat(getAlpha(), in ? 1 : 0);
+ mFadeAnimator.setDuration(in? FADE_DURATION_IN : FADE_DURATION_OUT);
+ mFadeAnimator.setInterpolator(in ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ mFadeAnimator.addListener(mFadeListener);
+ mFadeAnimator.addUpdateListener(mAlphaListener);
+ mFadeAnimator.start();
+ setVisibility(View.VISIBLE);
+ }
+
public ArrayList<View> getViews() {
return mViews;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 824960e..46b4078 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -24,6 +24,7 @@
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import com.android.internal.statusbar.StatusBarIcon;
@@ -56,7 +57,14 @@
mIconSize = iconSize;
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
+ if (statusIcons instanceof StatusIconContainer) {
+ setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
+ } else {
+ setShouldRestrictIcons(false);
+ }
setLayoutParams(mStatusIcons.getLayoutParams());
+ setPadding(mStatusIcons.getPaddingLeft(),mStatusIcons.getPaddingTop(),
+ mStatusIcons.getPaddingRight(), mStatusIcons.getPaddingBottom());
setOrientation(mStatusIcons.getOrientation());
setGravity(Gravity.CENTER_VERTICAL); // no LL.getGravity()
ViewGroup p = (ViewGroup) mStatusIcons.getParent();
@@ -77,6 +85,7 @@
for (int i = 0; i < getChildCount(); i++) {
StatusIconDisplayable child = (StatusIconDisplayable) getChildAt(i);
child.setStaticDrawableColor(mColor);
+ child.setDecorColor(mColor);
}
}
@@ -189,11 +198,12 @@
}
StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.SYSTEM, iconId, 0, 0, "Demo");
icon.visible = true;
- StatusBarIconView v = new StatusBarIconView(getContext(), null, null);
+ StatusBarIconView v = new StatusBarIconView(getContext(), slot, null, false);
v.setTag(slot);
v.set(icon);
v.setStaticDrawableColor(mColor);
- addView(v, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ v.setDecorColor(mColor);
+ addView(v, 0, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
}
public void addDemoWifiView(WifiIconState state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 91cf8f0..4885c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -168,10 +168,10 @@
}
}
- public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDisatchers) {
- mButtonDispatchers = buttonDisatchers;
- for (int i = 0; i < buttonDisatchers.size(); i++) {
- initiallyFill(buttonDisatchers.valueAt(i));
+ public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) {
+ mButtonDispatchers = buttonDispatchers;
+ for (int i = 0; i < buttonDispatchers.size(); i++) {
+ initiallyFill(buttonDispatchers.valueAt(i));
}
}
@@ -220,7 +220,8 @@
// and will only happen once.
if (parent.getChildAt(i).getId() == buttonDispatcher.getId()) {
buttonDispatcher.addView(parent.getChildAt(i));
- } else if (parent.getChildAt(i) instanceof ViewGroup) {
+ }
+ if (parent.getChildAt(i) instanceof ViewGroup) {
addAll(buttonDispatcher, (ViewGroup) parent.getChildAt(i));
}
}
@@ -411,7 +412,8 @@
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
mButtonDispatchers.valueAt(indexOfKey).addView(v);
- } else if (v instanceof ViewGroup) {
+ }
+ if (v instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup)v;
final int N = viewGroup.getChildCount();
for (int i = 0; i < N; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6dbe9f8..6cc96da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -260,6 +260,8 @@
new ButtonDispatcher(R.id.accessibility_button));
mButtonDispatchers.put(R.id.rotate_suggestion,
new ButtonDispatcher(R.id.rotate_suggestion));
+ mButtonDispatchers.put(R.id.menu_container,
+ new ButtonDispatcher(R.id.menu_container));
mDeadZone = new DeadZone(this);
}
@@ -368,6 +370,10 @@
return mButtonDispatchers.get(R.id.rotate_suggestion);
}
+ public ButtonDispatcher getMenuContainer() {
+ return mButtonDispatchers.get(R.id.menu_container);
+ }
+
public SparseArray<ButtonDispatcher> getButtonDispatchers() {
return mButtonDispatchers;
}
@@ -796,6 +802,10 @@
public boolean isRotateButtonVisible() { return mShowRotateButton; }
+ public void setMenuContainerVisibility(boolean visible) {
+ getMenuContainer().animateFade(visible);
+ }
+
@Override
public void onFinishInflate() {
mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 8bb73da..b650944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -199,7 +199,6 @@
private ValueAnimator mQsSizeChangeAnimator;
private boolean mShowEmptyShadeView;
- private boolean mShowDndView;
private boolean mQsScrimEnabled = true;
private boolean mLastAnnouncementWasQuickSettings;
@@ -1600,8 +1599,8 @@
// When only empty shade view is visible in QS collapsed state, simulate that we would have
// it in expanded QS state as well so we don't run into troubles when fading the view in/out
// and expanding/collapsing the whole panel from/to quick settings.
- if ((mNotificationStackScroller.getNotGoneChildCount() == 0
- && mShowEmptyShadeView) || mShowDndView) {
+ if (mNotificationStackScroller.getNotGoneChildCount() == 0
+ && mShowEmptyShadeView) {
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -2244,17 +2243,13 @@
return mDozing;
}
- public void showDndView(boolean dndViewVisible) {
- mShowDndView = dndViewVisible;
- mNotificationStackScroller.updateDndView(mShowDndView && !mQsExpanded);
- }
-
public void showEmptyShadeView(boolean emptyShadeViewVisible) {
mShowEmptyShadeView = emptyShadeViewVisible;
updateEmptyShadeView();
}
private void updateEmptyShadeView() {
+
// Hide "No notifications" in QS.
mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 6b0ac94..d9ba313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -327,7 +327,7 @@
- mNavigationBarView.getPaddingTop();
final int x1, x2, y1, y2;
if (mIsVertical) {
- x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingStart();
+ x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingLeft();
x2 = x1 + mTrackThickness;
y1 = mDragPositive ? height / 2 : mTrackPadding;
y2 = y1 + height / 2 - mTrackPadding;
@@ -401,6 +401,10 @@
mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
mTrackAnimator.setFloatValues(0, 1);
mTrackAnimator.start();
+
+ // Hide menu buttons on nav bar until quick scrub has ended
+ mNavigationBarView.setMenuContainerVisibility(false /* visible */);
+
try {
mOverviewEventSender.getProxy().onQuickScrubStart();
if (DEBUG_OVERVIEW_PROXY) {
@@ -416,6 +420,10 @@
private void endQuickScrub(boolean animate) {
if (mQuickScrubActive || mDragScrubActive) {
animateEnd();
+
+ // Restore the nav bar menu buttons visibility
+ mNavigationBarView.setMenuContainerVisibility(true /* visible */);
+
if (mQuickScrubActive) {
try {
mOverviewEventSender.getProxy().onQuickScrubEnd();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5f07599..061677c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -20,7 +20,6 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.provider.Settings.Global.ZEN_MODE_OFF;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
@@ -169,7 +168,6 @@
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
@@ -190,7 +188,6 @@
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -416,7 +413,7 @@
protected NotificationViewHierarchyManager mViewHierarchyManager;
protected AppOpsListener mAppOpsListener;
protected KeyguardViewMediator mKeyguardViewMediator;
- protected ZenModeController mZenController;
+ private ZenModeController mZenController;
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -881,7 +878,6 @@
mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
inflateEmptyShadeView();
- inflateDndView();
inflateFooterView();
mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
@@ -1149,7 +1145,6 @@
protected void reevaluateStyles() {
inflateFooterView();
updateFooter();
- inflateDndView();
inflateEmptyShadeView();
updateEmptyShadeView();
}
@@ -1171,19 +1166,6 @@
mStackScroller.setEmptyShadeView(mEmptyShadeView);
}
- private void inflateDndView() {
- if (mStackScroller == null) {
- return;
- }
- mDndView = (DndSuppressingNotificationsView) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_dnd_suppressing_notifications, mStackScroller, false);
- mDndView.setOnContentClickListener(v -> {
- Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
- startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
- });
- mStackScroller.setDndView(mDndView);
- }
-
private void inflateFooterView() {
if (mStackScroller == null) {
return;
@@ -1477,11 +1459,9 @@
@VisibleForTesting
protected void updateFooter() {
boolean showFooterView = mState != StatusBarState.KEYGUARD
- && !areNotificationsHidden()
&& mEntryManager.getNotificationData().getActiveNotifications().size() != 0
&& !mRemoteInputManager.getController().isRemoteInputActive();
boolean showDismissView = mClearAllEnabled && mState != StatusBarState.KEYGUARD
- && !areNotificationsHidden()
&& hasActiveClearableNotifications();
mStackScroller.updateFooterView(showFooterView, showDismissView);
@@ -1504,13 +1484,10 @@
return false;
}
- @VisibleForTesting
- protected void updateEmptyShadeView() {
- boolean showDndView = mState != StatusBarState.KEYGUARD && areNotificationsHidden();
- boolean showEmptyShadeView = !showDndView
- && mState != StatusBarState.KEYGUARD
- && mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
- mNotificationPanel.showDndView(showDndView);
+ private void updateEmptyShadeView() {
+ boolean showEmptyShadeView =
+ mState != StatusBarState.KEYGUARD &&
+ mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
mNotificationPanel.showEmptyShadeView(showEmptyShadeView);
}
@@ -5017,7 +4994,6 @@
protected NotificationShelf mNotificationShelf;
protected FooterView mFooterView;
protected EmptyShadeView mEmptyShadeView;
- protected DndSuppressingNotificationsView mDndView;
protected AssistManager mAssistManager;
@@ -5502,11 +5478,6 @@
mStackScroller.getChildCount() - offsetFromEnd++);
}
- if (mDndView != null) {
- mStackScroller.changeViewPosition(mDndView,
- mStackScroller.getChildCount() - offsetFromEnd++);
- }
-
mStackScroller.changeViewPosition(mEmptyShadeView,
mStackScroller.getChildCount() - offsetFromEnd++);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index c97c8eb..8398879 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -73,19 +73,23 @@
public StatusIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
+ initDimens();
+ setWillNotDraw(!DEBUG_OVERFLOW);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- setWillNotDraw(!DEBUG_OVERFLOW);
- initDimens();
}
public void setShouldRestrictIcons(boolean should) {
mShouldRestrictIcons = should;
}
+ public boolean isRestrictingIcons() {
+ return mShouldRestrictIcons;
+ }
+
private void initDimens() {
// This is the same value that StatusBarIconView uses
mIconDotFrameWidth = getResources().getDimensionPixelSize(
@@ -209,8 +213,8 @@
int childCount = getChildCount();
// Underflow === don't show content until that index
int firstUnderflowIndex = -1;
- if (DEBUG) android.util.Log.d(TAG, "calculateIconTransitions: start=" + translationX
- + " width=" + width);
+ if (DEBUG) android.util.Log.d(TAG, "calculateIconTranslations: start=" + translationX
+ + " width=" + width + " underflow=" + mNeedsUnderflow);
// Collect all of the states which want to be visible
for (int i = childCount - 1; i >= 0; i--) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 6a8d3a5..48a9fb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -20,6 +20,7 @@
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
@@ -30,6 +31,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
/**
* Base class for dialogs that should appear over panels and keyguard.
*/
@@ -99,24 +101,40 @@
}
public static void registerDismissListener(Dialog dialog) {
- boolean[] registered = new boolean[1];
- Context context = dialog.getContext();
- final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (dialog != null) {
- dialog.dismiss();
- }
- }
- };
- context.registerReceiverAsUser(mReceiver, UserHandle.CURRENT,
- new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), null, null);
- registered[0] = true;
- dialog.setOnDismissListener(d -> {
- if (registered[0]) {
- context.unregisterReceiver(mReceiver);
- registered[0] = false;
- }
- });
+ DismissReceiver dismissReceiver = new DismissReceiver(dialog);
+ dismissReceiver.register();
}
-}
+
+ private static class DismissReceiver extends BroadcastReceiver implements OnDismissListener {
+ private static final IntentFilter INTENT_FILTER = new IntentFilter();
+ static {
+ INTENT_FILTER.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
+ }
+
+ private final Dialog mDialog;
+ private boolean mRegistered;
+
+ DismissReceiver(Dialog dialog) {
+ mDialog = dialog;
+ }
+
+ void register() {
+ mDialog.getContext()
+ .registerReceiverAsUser(this, UserHandle.CURRENT, INTENT_FILTER, null, null);
+ mRegistered = true;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mDialog.dismiss();
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mRegistered) {
+ mDialog.getContext().unregisterReceiver(this);
+ mRegistered = false;
+ }
+ }
+ }}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index eeaa6cb..5275e27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -81,7 +81,6 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
@@ -237,7 +236,6 @@
protected boolean mScrollingEnabled;
protected FooterView mFooterView;
protected EmptyShadeView mEmptyShadeView;
- protected DndSuppressingNotificationsView mDndView;
private boolean mDismissAllInProgress;
private boolean mFadeNotificationsOnDismiss;
@@ -1008,8 +1006,7 @@
private float getAppearEndPosition() {
int appearPosition;
int notGoneChildCount = getNotGoneChildCount();
- if ((mEmptyShadeView.getVisibility() == GONE && mDndView.getVisibility() == GONE)
- && notGoneChildCount != 0) {
+ if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
if (isHeadsUpTransition()
|| (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
appearPosition = getTopHeadsUpPinnedHeight();
@@ -1019,8 +1016,6 @@
appearPosition += mShelf.getIntrinsicHeight();
}
}
- } else if (mEmptyShadeView.getVisibility() == GONE) {
- appearPosition = mDndView.getHeight();
} else {
appearPosition = mEmptyShadeView.getHeight();
}
@@ -2613,6 +2608,19 @@
return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
}
+ public int getFirstChildIntrinsicHeight() {
+ final ExpandableView firstChild = getFirstChildNotGone();
+ int firstChildMinHeight = firstChild != null
+ ? firstChild.getIntrinsicHeight()
+ : mEmptyShadeView != null
+ ? mEmptyShadeView.getIntrinsicHeight()
+ : mCollapsedSize;
+ if (mOwnScrollY > 0) {
+ firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
+ }
+ return firstChildMinHeight;
+ }
+
public float getTopPaddingOverflow() {
return mTopPaddingOverflow;
}
@@ -3910,7 +3918,6 @@
final int textColor = Utils.getColorAttr(context, R.attr.wallpaperTextColor);
mFooterView.setTextColor(textColor);
mEmptyShadeView.setTextColor(textColor);
- mDndView.setColor(textColor);
}
public void goToFullShade(long delay) {
@@ -3918,7 +3925,6 @@
mFooterView.setInvisible();
}
mEmptyShadeView.setInvisible();
- mDndView.setInvisible();
mGoToFullShadeNeedsAnimation = true;
mGoToFullShadeDelay = delay;
mNeedsAnimation = true;
@@ -4070,39 +4076,25 @@
int newVisibility = visible ? VISIBLE : GONE;
boolean changedVisibility = oldVisibility != newVisibility;
- if (changedVisibility) {
+ if (changedVisibility || newVisibility != GONE) {
if (newVisibility != GONE) {
- showFooterView(mEmptyShadeView);
+ int oldText = mEmptyShadeView.getTextResource();
+ int newText;
+ if (mStatusBar.areNotificationsHidden()) {
+ newText = R.string.dnd_suppressing_shade_text;
+ } else {
+ newText = R.string.empty_shade_text;
+ }
+ if (changedVisibility || !Objects.equals(oldText, newText)) {
+ mEmptyShadeView.setText(newText);
+ showFooterView(mEmptyShadeView);
+ }
} else {
hideFooterView(mEmptyShadeView, true);
}
}
}
- public void setDndView(DndSuppressingNotificationsView dndView) {
- int index = -1;
- if (mDndView != null) {
- index = indexOfChild(mDndView);
- removeView(mDndView);
- }
- mDndView = dndView;
- addView(mDndView, index);
- }
-
- public void updateDndView(boolean visible) {
- int oldVisibility = mDndView.willBeGone() ? GONE : mDndView.getVisibility();
- int newVisibility = visible ? VISIBLE : GONE;
-
- boolean changedVisibility = oldVisibility != newVisibility;
- if (changedVisibility) {
- if (newVisibility != GONE) {
- showFooterView(mDndView);
- } else {
- hideFooterView(mDndView, true);
- }
- }
- }
-
public void updateFooterView(boolean visible, boolean showDismissView) {
if (mFooterView == null) {
return;
@@ -4127,16 +4119,10 @@
} else {
footerView.setInvisible();
}
- Runnable onShowFinishRunnable = new Runnable() {
- @Override
- public void run() {
- footerView.setVisibility(VISIBLE);
- footerView.setWillBeGone(false);
- updateContentHeight();
- notifyHeightChangeListener(footerView);
- }
- };
- footerView.performVisibilityAnimation(true, onShowFinishRunnable);
+ footerView.setVisibility(VISIBLE);
+ footerView.setWillBeGone(false);
+ updateContentHeight();
+ notifyHeightChangeListener(footerView);
}
private void hideFooterView(StackScrollerDecorView footerView, boolean isButtonVisible) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index 9a28657..210764a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -21,9 +21,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -35,6 +32,7 @@
import java.util.Collections;
import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicBoolean;
import androidx.slice.SliceProvider;
import androidx.slice.SliceSpecs;
@@ -58,12 +56,24 @@
@Test
public void showSlice_notifiesListener() {
ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
- boolean[] notified = {false};
+ AtomicBoolean notified = new AtomicBoolean();
mKeyguardSliceView.setContentChangeListener((hasHeader)-> {
- notified[0] = true;
+ notified.set(true);
});
mKeyguardSliceView.onChanged(builder.build());
- Assert.assertTrue("Listener should be notified about slice changes.", notified[0]);
+ Assert.assertTrue("Listener should be notified about slice changes.",
+ notified.get());
+ }
+
+ @Test
+ public void showSlice_emptySliceNotifiesListener() {
+ AtomicBoolean notified = new AtomicBoolean();
+ mKeyguardSliceView.setContentChangeListener((hasHeader)-> {
+ notified.set(true);
+ });
+ mKeyguardSliceView.onChanged(null);
+ Assert.assertTrue("Listener should be notified about slice changes.",
+ notified.get());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index ab042d4..2a4a5ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -298,4 +298,13 @@
assertEquals(3, mGroupRow.getNumUniqueChannels());
}
+
+ @Test
+ public void testIconScrollXAfterTranslationAndReset() throws Exception {
+ mGroupRow.setTranslation(50);
+ assertEquals(50, -mGroupRow.getEntry().expandedIcon.getScrollX());
+
+ mGroupRow.resetTranslation();
+ assertEquals(0, mGroupRow.getEntry().expandedIcon.getScrollX());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
index d3c3746..8bdaff9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
@@ -18,6 +18,11 @@
import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER;
import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
import static junit.framework.Assert.assertEquals;
@@ -312,6 +317,40 @@
assertFalse(mNotificationData.shouldSuppressAmbient(entry));
}
+ @Test
+ public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
+ initStatusBarNotification(false);
+ when(mMockStatusBarNotification.getKey()).thenReturn(
+ TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+ NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+ entry.mIsSystemNotification = true;
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_CALL).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+ assertTrue(mNotificationData.shouldSuppressAmbient(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_REMINDER).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_ALARM).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_EVENT).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_MESSAGE).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+ }
+
private void initStatusBarNotification(boolean allowDuringSetup) {
Bundle bundle = new Bundle();
bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardPresentationTest.java
new file mode 100644
index 0000000..5429153
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardPresentationTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class KeyguardPresentationTest extends SysuiTestCase {
+ @Test
+ public void testInflation_doesntCrash() {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ inflater.inflate(R.layout.keyguard_presentation, null);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 41cf869..37e0005 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -78,7 +78,6 @@
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.AppOpsListener;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.FooterView;
import com.android.systemui.statusbar.FooterViewButton;
@@ -104,7 +103,6 @@
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import org.junit.Before;
@@ -134,7 +132,6 @@
@Mock private ScrimController mScrimController;
@Mock private ArrayList<Entry> mNotificationList;
@Mock private FingerprintUnlockController mFingerprintUnlockController;
- @Mock private ZenModeController mZenController;
@Mock private NotificationData mNotificationData;
// Mock dependencies:
@@ -166,7 +163,6 @@
mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
- mDependency.injectTestDependency(ZenModeController.class, mZenController);
mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -217,7 +213,7 @@
mRemoteInputManager, mock(NotificationGroupManager.class),
mock(FalsingManager.class), mock(StatusBarWindowManager.class),
mock(NotificationIconAreaController.class), mock(DozeScrimController.class),
- mock(NotificationShelf.class), mLockscreenUserManager, mZenController,
+ mock(NotificationShelf.class), mLockscreenUserManager,
mock(CommandQueue.class));
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
@@ -680,60 +676,6 @@
}
@Test
- public void testDNDView_atEnd() {
- // add footer
- mStatusBar.reevaluateStyles();
-
- // add notification
- ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
- mStackScroller.addContainerView(row);
-
- mStatusBar.onUpdateRowStates();
-
- // move dnd view to end
- verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
- verify(mStackScroller).changeViewPosition(any(DndSuppressingNotificationsView.class),
- eq(-2 /* end */));
- }
-
- @Test
- public void updateEmptyShade_nonNotificationsDndOff() {
- mStatusBar.setBarStateForTest(StatusBarState.SHADE);
- when(mNotificationData.getActiveNotifications()).thenReturn(new ArrayList<>());
- assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
-
- mStatusBar.updateEmptyShadeView();
- verify(mNotificationPanelView).showDndView(false);
- verify(mNotificationPanelView).showEmptyShadeView(true);
- }
-
- @Test
- public void updateEmptyShade_noNotificationsDndOn() {
- mStatusBar.setBarStateForTest(StatusBarState.SHADE);
- when(mNotificationData.getActiveNotifications()).thenReturn(new ArrayList<>());
- assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
- when(mZenController.areNotificationsHiddenInShade()).thenReturn(true);
-
- mStatusBar.updateEmptyShadeView();
- verify(mNotificationPanelView).showDndView(true);
- verify(mNotificationPanelView).showEmptyShadeView(false);
- }
-
- @Test
- public void updateEmptyShade_yesNotificationsDndOff() {
- mStatusBar.setBarStateForTest(StatusBarState.SHADE);
- ArrayList<Entry> entries = new ArrayList<>();
- entries.add(mock(Entry.class));
- when(mNotificationData.getActiveNotifications()).thenReturn(entries);
- assertEquals(1, mEntryManager.getNotificationData().getActiveNotifications().size());
- when(mZenController.areNotificationsHiddenInShade()).thenReturn(false);
-
- mStatusBar.updateEmptyShadeView();
- verify(mNotificationPanelView).showDndView(false);
- verify(mNotificationPanelView).showEmptyShadeView(false);
- }
-
- @Test
public void testSetState_changesIsFullScreenUserSwitcherState() {
mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
assertFalse(mStatusBar.isFullScreenUserSwitcherState());
@@ -779,7 +721,6 @@
DozeScrimController dozeScrimController,
NotificationShelf notificationShelf,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- ZenModeController zenController,
CommandQueue commandQueue) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
@@ -808,7 +749,6 @@
mDozeScrimController = dozeScrimController;
mNotificationShelf = notificationShelf;
mLockscreenUserManager = notificationLockscreenUserManager;
- mZenController = zenController;
mCommandQueue = commandQueue;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index 3d17ec4..eeb4209 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -18,7 +18,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -35,7 +34,6 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.TestableDependency;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FooterView;
import com.android.systemui.statusbar.NotificationBlockingHelperManager;
@@ -71,7 +69,6 @@
@Mock private NotificationGroupManager mGroupManager;
@Mock private ExpandHelper mExpandHelper;
@Mock private EmptyShadeView mEmptyShadeView;
- @Mock private DndSuppressingNotificationsView mDndView;
@Before
@UiThreadTest
@@ -89,7 +86,6 @@
mStackScroller.setHeadsUpManager(mHeadsUpManager);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setEmptyShadeView(mEmptyShadeView);
- mStackScroller.setDndView(mDndView);
// Stub out functionality that isn't necessary to test.
doNothing().when(mBar)
@@ -124,6 +120,40 @@
}
@Test
+ public void updateEmptyView_dndSuppressing() {
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
+ when(mBar.areNotificationsHidden()).thenReturn(true);
+
+ mStackScroller.updateEmptyShadeView(true);
+
+ verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
+ }
+
+ @Test
+ public void updateEmptyView_dndNotSuppressing() {
+ mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
+ when(mBar.areNotificationsHidden()).thenReturn(false);
+
+ mStackScroller.updateEmptyShadeView(true);
+
+ verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+ }
+
+ @Test
+ public void updateEmptyView_noNotificationsToDndSuppressing() {
+ mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
+ when(mBar.areNotificationsHidden()).thenReturn(false);
+ mStackScroller.updateEmptyShadeView(true);
+ verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+
+ when(mBar.areNotificationsHidden()).thenReturn(true);
+ mStackScroller.updateEmptyShadeView(true);
+ verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
+ }
+
+ @Test
@UiThreadTest
public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
mStackScroller.setExpandedHeight(0f);
@@ -143,7 +173,7 @@
mStackScroller.updateFooterView(true, false);
- verify(view).performVisibilityAnimation(eq(true), any());
+ verify(view).setVisibility(View.VISIBLE);
verify(view).performSecondaryVisibilityAnimation(false);
}
@@ -156,7 +186,7 @@
mStackScroller.updateFooterView(true, true);
- verify(view).performVisibilityAnimation(eq(true), any());
+ verify(view).setVisibility(View.VISIBLE);
verify(view).performSecondaryVisibilityAnimation(true);
}
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 7dd85ba..d61f228 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5740,6 +5740,41 @@
// OS: P
ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS = 1406;
+ // ACTION: Storage initialization wizard initialization choice of external/portable
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_INIT_EXTERNAL = 1407;
+
+ // ACTION: Storage initialization wizard initialization choice of internal/adoptable
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_INIT_INTERNAL = 1408;
+
+ // ACTION: Storage initialization wizard benchmark fast choice of continue
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_FAST_CONTINUE = 1409;
+
+ // ACTION: Storage initialization wizard benchmark slow choice of continue
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_SLOW_CONTINUE = 1410;
+
+ // ACTION: Storage initialization wizard benchmark slow choice of abort
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_SLOW_ABORT = 1411;
+
+ // ACTION: Storage initialization wizard migration choice of now
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_MIGRATE_NOW = 1412;
+
+ // ACTION: Storage initialization wizard migration choice of later
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_MIGRATE_LATER = 1413;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index 90baea0..cc7304a 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -629,6 +629,8 @@
mFullBackupTask.unregisterTask();
switch (mStatus) {
case BackupTransport.TRANSPORT_OK:
+ case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
+ case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.SUCCESS);
break;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 99944625..72f9d74 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -132,6 +132,7 @@
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
@@ -1992,13 +1993,6 @@
return ret;
}
- private boolean argsContain(String[] args, String target) {
- for (String arg : args) {
- if (target.equals(arg)) return true;
- }
- return false;
- }
-
private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
final long DIAG_TIME_MS = 5000;
@@ -2027,10 +2021,10 @@
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
if (asProto) return;
- if (argsContain(args, DIAG_ARG)) {
+ if (ArrayUtils.contains(args, DIAG_ARG)) {
dumpNetworkDiagnostics(pw);
return;
- } else if (argsContain(args, TETHERING_ARG)) {
+ } else if (ArrayUtils.contains(args, TETHERING_ARG)) {
mTethering.dump(fd, pw, args);
return;
}
@@ -2098,7 +2092,7 @@
pw.println();
mMultipathPolicyTracker.dump(pw);
- if (argsContain(args, SHORT_ARG) == false) {
+ if (ArrayUtils.contains(args, SHORT_ARG) == false) {
pw.println();
synchronized (mValidationLogs) {
pw.println("mValidationLogs (most recent first):");
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 6c35bda..00302b2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2541,11 +2541,6 @@
synchronized (mLock) {
mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
}
- if (userId == UserHandle.USER_SYSTEM) {
- String propertyName = "sys.user." + userId + ".ce_available";
- Slog.d(TAG, "Setting property: " + propertyName + "=true");
- SystemProperties.set(propertyName, "true");
- }
}
@Override
@@ -2685,7 +2680,8 @@
}
// Ignore requests to create directories if CE storage is not available
- if (!SystemProperties.getBoolean(propertyName, false)) {
+ if ((userId == UserHandle.USER_SYSTEM)
+ && !SystemProperties.getBoolean(propertyName, false)) {
throw new IllegalStateException("Failed to prepare " + appPath);
}
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 26a8cf7..f24d8cd 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -71,6 +71,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.function.Predicate;
public class TextServicesManagerService extends ITextServicesManager.Stub {
private static final String TAG = TextServicesManagerService.class.getSimpleName();
@@ -396,10 +397,7 @@
final String packageName = sci.getPackageName();
final int change = isPackageDisappearing(packageName);
if (DBG) Slog.d(TAG, "Changing package name: " + packageName);
- if (// Package disappearing
- change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE
- // Package modified
- || isPackageModified(packageName)) {
+ if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
SpellCheckerInfo availSci =
findAvailSystemSpellCheckerLocked(packageName, tsd);
// Set the spell checker settings if different than before
@@ -885,6 +883,11 @@
}
synchronized (mLock) {
mListeners.unregister(listener);
+ final IBinder scListenerBinder = listener.asBinder();
+ final Predicate<SessionRequest> removeCondition =
+ request -> request.mScListener.asBinder() == scListenerBinder;
+ mPendingSessionRequests.removeIf(removeCondition);
+ mOnGoingSessionRequests.removeIf(removeCondition);
cleanLocked();
}
}
@@ -934,6 +937,7 @@
if (mUnbindCalled) {
return;
}
+ mListeners.register(request.mScListener);
if (!mConnected) {
mPendingSessionRequests.add(request);
return;
@@ -959,7 +963,6 @@
if (mOnGoingSessionRequests.remove(request)) {
try {
request.mTsListener.onServiceConnected(newSession);
- mListeners.register(request.mScListener);
} catch (RemoteException e) {
// Technically this can happen if the spell checker client app is already
// dead. We can just forget about this request; the request is already
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f413639..b32ece7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -108,6 +108,8 @@
private static final boolean LOG_SERVICE_START_STOP = false;
+ private static final boolean SHOW_DUNGEON_NOTIFICATION = false;
+
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
@@ -942,6 +944,10 @@
smap.mActiveForegroundAppsChanged = false;
}
+ if (!SHOW_DUNGEON_NOTIFICATION) {
+ return;
+ }
+
final NotificationManager nm = (NotificationManager) mAm.mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
final Context context = mAm.mContext;
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 1149e87..7599afa 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -20,33 +20,41 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;
-import com.android.server.pm.UserManagerService;
-import java.io.FileDescriptor;
+
/**
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
* screen immediately after the dialog shows so that the user is informed that something is
* happening in the background rather than just freeze the screen and not know if the user-switch
* affordance was being handled.
- *
*/
final class CarUserSwitchingDialog extends UserSwitchingDialog {
+
private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
- UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
- String switchingToSystemUserMessage) {
+ UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
+ String switchingToSystemUserMessage) {
super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
- switchingToSystemUserMessage);
+ switchingToSystemUserMessage);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
@@ -58,18 +66,104 @@
Resources res = getContext().getResources();
// Custom view due to alignment and font size requirements
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
- null);
+ null);
UserManager userManager =
(UserManager) getContext().getSystemService(Context.USER_SERVICE);
Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
if (bitmap != null) {
+ CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(bitmap,
+ res.getDimension(R.dimen.car_fullscreen_user_pod_image_avatar_height));
((ImageView) view.findViewById(R.id.user_loading_avatar))
- .setImageBitmap(bitmap);
+ .setImageDrawable(drawable);
}
((TextView) view.findViewById(R.id.user_loading))
- .setText(res.getString(R.string.car_loading_profile));
+ .setText(res.getString(R.string.car_loading_profile));
setView(view);
}
+
+ /**
+ * Converts the user icon to a circularly clipped one. This is used in the User Picker and
+ * Settings.
+ */
+ static class CircleFramedDrawable extends Drawable {
+
+ private final Bitmap mBitmap;
+ private final int mSize;
+ private final Paint mPaint;
+
+ private float mScale;
+ private Rect mSrcRect;
+ private RectF mDstRect;
+
+ public static CircleFramedDrawable getInstance(Bitmap icon, float iconSize) {
+ CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
+ return instance;
+ }
+
+ public CircleFramedDrawable(Bitmap icon, int size) {
+ super();
+ mSize = size;
+
+ mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(mBitmap);
+
+ final int width = icon.getWidth();
+ final int height = icon.getHeight();
+ final int square = Math.min(width, height);
+
+ final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2,
+ square, square);
+ final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
+
+ final Path fillPath = new Path();
+ fillPath.addArc(circleRect, 0f, 360f);
+
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+ // opaque circle
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(Color.BLACK);
+ mPaint.setStyle(Paint.Style.FILL);
+ canvas.drawPath(fillPath, mPaint);
+
+ // mask in the icon where the bitmap is opaque
+ mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
+
+ // prepare paint for frame drawing
+ mPaint.setXfermode(null);
+
+ mScale = 1f;
+
+ mSrcRect = new Rect(0, 0, mSize, mSize);
+ mDstRect = new RectF(0, 0, mSize, mSize);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final float inside = mScale * mSize;
+ final float pad = (mSize - inside) / 2f;
+
+ mDstRect.set(pad, pad, mSize - pad, mSize - pad);
+ canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // Needed to implement abstract method. Do nothing.
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // Needed to implement abstract method. Do nothing.
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index b5047ae..a88f408 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -238,7 +238,9 @@
final ActivityStack targetStack = mDefaultDisplay.getStack(
WINDOWING_MODE_UNDEFINED, mTargetActivityType);
- final ActivityRecord targetActivity = targetStack.getTopActivity();
+ final ActivityRecord targetActivity = targetStack != null
+ ? targetStack.getTopActivity()
+ : null;
if (DEBUG) Slog.d(TAG, "onAnimationFinished(): targetStack=" + targetStack
+ " targetActivity=" + targetActivity
+ " mRestoreTargetBehindStack=" + mRestoreTargetBehindStack);
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index f427819..ac74598 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -20,6 +20,7 @@
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
+import android.net.ip.IpClient;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.IpConnectivityLog;
import android.os.Binder;
@@ -269,10 +270,12 @@
// Dump the rolling buffer of metrics event and pretty print events using a human readable
// format. Also print network dns/connect statistics and default network event time series.
static final String CMD_LIST = "list";
- // By default any other argument will fall into the default case which is remapped to the
- // "list" command. This includes most notably bug reports collected by dumpsys.cpp with
- // the "-a" argument.
- static final String CMD_DEFAULT = CMD_LIST;
+ // Dump all IpClient logs ("ipclient").
+ static final String CMD_IPCLIENT = IpClient.DUMP_ARG;
+ // By default any other argument will fall into the default case which is the equivalent
+ // of calling both the "list" and "ipclient" commands. This includes most notably bug
+ // reports collected by dumpsys.cpp with the "-a" argument.
+ static final String CMD_DEFAULT = "";
@Override
public int logEvent(ConnectivityMetricsEvent event) {
@@ -292,9 +295,20 @@
case CMD_PROTO:
cmdListAsProto(pw);
return;
- case CMD_LIST: // fallthrough
+ case CMD_IPCLIENT: {
+ final String[] ipclientArgs = ((args != null) && (args.length > 1))
+ ? Arrays.copyOfRange(args, 1, args.length)
+ : null;
+ IpClient.dumpAllLogs(pw, ipclientArgs);
+ return;
+ }
+ case CMD_LIST:
+ cmdList(pw);
+ return;
default:
cmdList(pw);
+ pw.println("");
+ IpClient.dumpAllLogs(pw, null);
return;
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b68ef11..bf17798 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4051,17 +4051,29 @@
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
r.setIsAppImportanceLocked(mRankingHelper.getIsAppImportanceLocked(pkg, callingUid));
- if ((notification.flags & FLAG_FOREGROUND_SERVICE) != 0
- && (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0
- && (r.getImportance() == IMPORTANCE_MIN || r.getImportance() == IMPORTANCE_NONE)) {
- // Increase the importance of foreground service notifications unless the user had an
- // opinion otherwise
- if (TextUtils.isEmpty(channelId)
- || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
- r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service");
- } else {
- channel.setImportance(IMPORTANCE_LOW);
- mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false);
+ if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+ final boolean fgServiceShown = channel.isFgServiceShown();
+ if (((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0
+ || !fgServiceShown)
+ && (r.getImportance() == IMPORTANCE_MIN
+ || r.getImportance() == IMPORTANCE_NONE)) {
+ // Increase the importance of foreground service notifications unless the user had
+ // an opinion otherwise (and the channel hasn't yet shown a fg service).
+ if (TextUtils.isEmpty(channelId)
+ || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
+ r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service");
+ } else {
+ channel.setImportance(IMPORTANCE_LOW);
+ if (!fgServiceShown) {
+ channel.unlockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+ channel.setFgServiceShown(true);
+ }
+ mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false);
+ r.updateNotificationChannel(channel);
+ }
+ } else if (!fgServiceShown && !TextUtils.isEmpty(channelId)
+ && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
+ channel.setFgServiceShown(true);
r.updateNotificationChannel(channel);
}
}
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index dbf0940..d0a3757 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import static android.content.Intent.FLAG_ACTIVITY_MATCH_EXTERNAL;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
@@ -366,6 +368,7 @@
final Intent failureIntent = new Intent(origIntent);
boolean requiresSecondPhase = false;
failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
+ failureIntent.setFlags(failureIntent.getFlags() & ~Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
failureIntent.setLaunchToken(token);
ArrayList<AuxiliaryResolveInfo.AuxiliaryFilter> filters = null;
boolean isWebIntent = origIntent.isWebIntent();
@@ -408,6 +411,10 @@
if (filters != null && !filters.isEmpty()) {
return new AuxiliaryResolveInfo(token, requiresSecondPhase, failureIntent, filters);
}
+ // if the match external flag is set, return an empty resolve info
+ if ((origIntent.getFlags() & FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
+ return new AuxiliaryResolveInfo(token, false, failureIntent, null /* filters */);
+ }
// Hash or filter mis-match; no instant apps for this domain.
return null;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f7a0215..fa934fe 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,7 +17,6 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -74,6 +73,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
@@ -111,9 +111,9 @@
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -154,6 +154,8 @@
private static final String ATTR_NAME = "name";
private static final String ATTR_INSTALL_REASON = "installRason";
+ private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
+
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -255,6 +257,8 @@
@GuardedBy("mLock")
private final List<String> mResolvedInstructionSets = new ArrayList<>();
@GuardedBy("mLock")
+ private final List<String> mResolvedNativeLibPaths = new ArrayList<>();
+ @GuardedBy("mLock")
private File mInheritedFilesBase;
private static final FileFilter sAddedFilter = new FileFilter() {
@@ -971,6 +975,26 @@
final File oatDir = new File(toDir, "oat");
createOatDirs(mResolvedInstructionSets, oatDir);
}
+ // pre-create lib dirs for linking if necessary
+ if (!mResolvedNativeLibPaths.isEmpty()) {
+ for (String libPath : mResolvedNativeLibPaths) {
+ // "/lib/arm64" -> ["lib", "arm64"]
+ final int splitIndex = libPath.lastIndexOf('/');
+ if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+ Slog.e(TAG, "Skipping native library creation for linking due to "
+ + "invalid path: " + libPath);
+ continue;
+ }
+ final String libDirPath = libPath.substring(1, splitIndex);
+ final File libDir = new File(toDir, libDirPath);
+ if (!libDir.exists()) {
+ NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+ }
+ final String archDirPath = libPath.substring(splitIndex + 1);
+ NativeLibraryHelper.createNativeLibrarySubdir(
+ new File(libDir, archDirPath));
+ }
+ }
linkFiles(fromFiles, toDir, mInheritedFilesBase);
} else {
// TODO: this should delegate to DCS so the system process
@@ -988,7 +1012,7 @@
computeProgressLocked(true);
// Unpack native libraries
- extractNativeLibraries(mResolvedStageDir, params.abiOverride);
+ extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
// We've reached point of no return; call into PMS to install the stage.
// Regardless of success or failure we always destroy session.
@@ -1028,6 +1052,17 @@
}
/**
+ * Returns true if the session should attempt to inherit any existing native libraries already
+ * extracted at the current install location. This is necessary to prevent double loading of
+ * native libraries already loaded by the running app.
+ */
+ private boolean mayInheritNativeLibs() {
+ return SystemProperties.getBoolean(PROPERTY_NAME_INHERIT_NATIVE, true) &&
+ params.mode == SessionParams.MODE_INHERIT_EXISTING &&
+ (params.installFlags & PackageManager.DONT_KILL_APP) != 0;
+ }
+
+ /**
* Validate install by confirming that all application packages are have
* consistent package name, version code, and signing certificates.
* <p>
@@ -1249,6 +1284,38 @@
}
}
}
+
+ // Inherit native libraries for DONT_KILL sessions.
+ if (mayInheritNativeLibs() && removeSplitList.isEmpty()) {
+ File[] libDirs = new File[]{
+ new File(packageInstallDir, NativeLibraryHelper.LIB_DIR_NAME),
+ new File(packageInstallDir, NativeLibraryHelper.LIB64_DIR_NAME)};
+ for (File libDir : libDirs) {
+ if (!libDir.exists() || !libDir.isDirectory()) {
+ continue;
+ }
+ final List<File> libDirsToInherit = new LinkedList<>();
+ for (File archSubDir : libDir.listFiles()) {
+ if (!archSubDir.isDirectory()) {
+ continue;
+ }
+ String relLibPath;
+ try {
+ relLibPath = getRelativePath(archSubDir, packageInstallDir);
+ } catch (IOException e) {
+ Slog.e(TAG, "Skipping linking of native library directory!", e);
+ // shouldn't be possible, but let's avoid inheriting these to be safe
+ libDirsToInherit.clear();
+ break;
+ }
+ if (!mResolvedNativeLibPaths.contains(relLibPath)) {
+ mResolvedNativeLibPaths.add(relLibPath);
+ }
+ libDirsToInherit.addAll(Arrays.asList(archSubDir.listFiles()));
+ }
+ mResolvedInheritedFiles.addAll(libDirsToInherit);
+ }
+ }
}
}
@@ -1374,11 +1441,13 @@
Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir);
}
- private static void extractNativeLibraries(File packageDir, String abiOverride)
+ private static void extractNativeLibraries(File packageDir, String abiOverride, boolean inherit)
throws PackageManagerException {
- // Always start from a clean slate
final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
- NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+ if (!inherit) {
+ // Start from a clean slate
+ NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+ }
NativeLibraryHelper.Handle handle = null;
try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 681b0c9..af5521d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16403,22 +16403,6 @@
}
}
- @Override
- public List<String> getPreviousCodePaths(String packageName) {
- final int callingUid = Binder.getCallingUid();
- final List<String> result = new ArrayList<>();
- if (getInstantAppPackageName(callingUid) != null) {
- return result;
- }
- final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null
- && ps.oldCodePaths != null
- && !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
- result.addAll(ps.oldCodePaths);
- }
- return result;
- }
-
private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, final @ParseFlags int parseFlags,
final @ScanFlags int scanFlags, UserHandle user, int[] allUsers,
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 898ecf3..f8bf9c4 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -844,7 +844,12 @@
}
// If what we are scanning is a system (and possibly privileged) package,
// then make it so, regardless of whether it was previously installed only
- // in the data partition.
+ // in the data partition. Reset first.
+ pkgSetting.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
+ pkgSetting.pkgPrivateFlags &= ~(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
+ | ApplicationInfo.PRIVATE_FLAG_OEM
+ | ApplicationInfo.PRIVATE_FLAG_VENDOR
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT);
pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 96c102b..045a295 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -24,6 +24,8 @@
import android.os.FileUtils;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.os.SystemProperties;
+import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -96,6 +98,14 @@
}
mInstaller.createUserData(volumeUuid, userId, userSerial, flags);
+
+ // CE storage is available after they are prepared.
+ if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 &&
+ (userId == UserHandle.USER_SYSTEM)) {
+ String propertyName = "sys.user." + userId + ".ce_available";
+ Slog.d(TAG, "Setting property: " + propertyName + "=true");
+ SystemProperties.set(propertyName, "true");
+ }
} catch (Exception e) {
logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid
+ " because we failed to prepare: " + e);
@@ -103,7 +113,8 @@
if (allowRecover) {
// Try one last time; if we fail again we're really in trouble
- prepareUserDataLI(volumeUuid, userId, userSerial, flags, false);
+ prepareUserDataLI(volumeUuid, userId, userSerial,
+ flags | StorageManager.FLAG_STORAGE_DE, false);
}
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index d1b48480..8214aad 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -426,7 +426,7 @@
return;
}
try {
- sStatsd.informDeviceShutdown(true);
+ sStatsd.informDeviceShutdown();
} catch (Exception e) {
Slog.w(TAG, "Failed to inform statsd of a shutdown event.", e);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 38fb30e..9621edd 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -393,6 +393,8 @@
/** Temporary float array to retrieve 3x3 matrix values. */
private final float[] mTmpFloats = new float[9];
+ private MagnificationSpec mMagnificationSpec;
+
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
final AppWindowToken atoken = w.mAppToken;
@@ -3837,10 +3839,22 @@
}
void applyMagnificationSpec(MagnificationSpec spec) {
+ if (spec.scale != 1.0) {
+ mMagnificationSpec = spec;
+ } else {
+ mMagnificationSpec = null;
+ }
+
applyMagnificationSpec(getPendingTransaction(), spec);
getPendingTransaction().apply();
}
+ void reapplyMagnificationSpec() {
+ if (mMagnificationSpec != null) {
+ applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec);
+ }
+ }
+
@Override
void onParentSet() {
// Since we are the top of the SurfaceControl hierarchy here
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 86aed47..0de3c92 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -808,6 +808,8 @@
void onParentSet() {
super.onParentSet();
setDrawnStateEvaluated(false /*evaluated*/);
+
+ getDisplayContent().reapplyMagnificationSpec();
}
@Override
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index d6999dd..63ae09a 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -54,6 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IState;
import com.android.internal.util.Preconditions;
@@ -74,6 +75,7 @@
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -100,6 +102,36 @@
private static final Class[] sMessageClasses = { IpClient.class, DhcpClient.class };
private static final SparseArray<String> sWhatToString =
MessageUtils.findMessageNames(sMessageClasses);
+ // Two static concurrent hashmaps of interface name to logging classes.
+ // One holds StateMachine logs and the other connectivity packet logs.
+ private static final ConcurrentHashMap<String, SharedLog> sSmLogs = new ConcurrentHashMap<>();
+ private static final ConcurrentHashMap<String, LocalLog> sPktLogs = new ConcurrentHashMap<>();
+
+ // If |args| is non-empty, assume it's a list of interface names for which
+ // we should print IpClient logs (filter out all others).
+ public static void dumpAllLogs(PrintWriter writer, String[] args) {
+ for (String ifname : sSmLogs.keySet()) {
+ if (!ArrayUtils.isEmpty(args) && !ArrayUtils.contains(args, ifname)) continue;
+
+ writer.println(String.format("--- BEGIN %s ---", ifname));
+
+ final SharedLog smLog = sSmLogs.get(ifname);
+ if (smLog != null) {
+ writer.println("State machine log:");
+ smLog.dump(null, writer, null);
+ }
+
+ writer.println("");
+
+ final LocalLog pktLog = sPktLogs.get(ifname);
+ if (pktLog != null) {
+ writer.println("Connectivity packet log:");
+ pktLog.readOnlyLocalLog().dump(null, writer, null);
+ }
+
+ writer.println(String.format("--- END %s ---", ifname));
+ }
+ }
/**
* Callbacks for handling IpClient events.
@@ -680,8 +712,10 @@
mShutdownLatch = new CountDownLatch(1);
mNwService = deps.getNMS();
- mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
- mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
+ sSmLogs.putIfAbsent(mInterfaceName, new SharedLog(MAX_LOG_RECORDS, mTag));
+ mLog = sSmLogs.get(mInterfaceName);
+ sPktLogs.putIfAbsent(mInterfaceName, new LocalLog(MAX_PACKET_RECORDS));
+ mConnectivityPacketLog = sPktLogs.get(mInterfaceName);
mMsgStateLogger = new MessageHandlingLogger();
// TODO: Consider creating, constructing, and passing in some kind of
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index 949c504..b1dad5a 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -419,7 +419,7 @@
runTask(task);
verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
- verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
}
@Test
@@ -467,8 +467,7 @@
verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS);
verify(mObserver).onResult(PACKAGE_2, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
- // TODO: Should we return the status of the last?
- verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
}
@Test
@@ -488,7 +487,7 @@
runTask(task);
verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
- verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
verify(agentMock.agent).onQuotaExceeded(anyLong(), anyLong());
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 58f5898..376cc64 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -557,11 +557,34 @@
assertEquals(IMPORTANCE_NONE,
mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
- final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
+ StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
sbn.getId(), sbn.getNotification(), sbn.getUserId());
waitForIdle();
+ // The first time a foreground service notification is shown, we allow the channel
+ // to be updated to allow it to be seen.
+ assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
+ assertEquals(IMPORTANCE_LOW,
+ mService.getNotificationRecord(sbn.getKey()).getImportance());
+ assertEquals(IMPORTANCE_LOW,
+ mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+ mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
+ waitForIdle();
+
+ update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
+ update.setFgServiceShown(true);
+ mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
+ waitForIdle();
+ assertEquals(IMPORTANCE_NONE,
+ mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+
+ sbn = generateNotificationRecord(channel).sbn;
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ waitForIdle();
+ // The second time it is shown, we keep the user's preference.
assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
assertNull(mService.getNotificationRecord(sbn.getKey()));
assertEquals(IMPORTANCE_NONE,
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 4ca175f..6ce66f0 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -98,7 +98,7 @@
private static final String LAUNCH_FILE = "applaunch.txt";
private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
private static final String DEFAULT_TRACE_CATEGORIES =
- "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm,binder_driver,hal";
+ "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm,binder_driver,hal,ss";
private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index fc46b9c..788924b 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -116,20 +116,6 @@
}
@Test
- public void testNetworkStatsSummary() throws Exception {
- stageFile(R.raw.net_dev_typical, file("net/dev"));
-
- final NetworkStats stats = mFactory.readNetworkStatsIfaceDev();
- assertEquals(6, stats.size());
- assertStatsEntry(stats, "lo", UID_ALL, SET_ALL, TAG_NONE, 8308L, 8308L);
- assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L, 489339L);
- assertStatsEntry(stats, "ifb0", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
- assertStatsEntry(stats, "ifb1", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
- assertStatsEntry(stats, "sit0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
- assertStatsEntry(stats, "ip6tnl0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
- }
-
- @Test
public void testNetworkStatsSingle() throws Exception {
stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 19c6c31..7f48544 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -598,10 +598,13 @@
// If no inner element exists, represent a unique identifier
out_resource->value = util::make_unique<Id>();
} else {
- // If an inner element exists, the inner element must be a reference to
- // another resource id
Reference* ref = ValueCast<Reference>(out_resource->value.get());
- if (!ref || ref->name.value().type != ResourceType::kId) {
+ if (ref && !ref->name && !ref->id) {
+ // A null reference also means there is no inner element when ids are in the form:
+ // <id name="name"/>
+ out_resource->value = util::make_unique<Id>();
+ } else if (!ref || ref->name.value().type != ResourceType::kId) {
+ // If an inner element exists, the inner element must be a reference to another resource id
diag_->Error(DiagMessage(out_resource->source)
<< "<" << parser->element_name()
<< "> inner element must either be a resource reference or empty");
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index c12b9fa..41b4041 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -944,20 +944,30 @@
ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull());
ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz"), NotNull());
+ input = R"(
+ <id name="foo2">@id/bar</id>
+ <id name="bar2"/>
+ <id name="baz2"></id>)";
+ ASSERT_TRUE(TestParse(input));
+
+ ASSERT_THAT(test::GetValue<Reference>(&table_, "id/foo2"), NotNull());
+ ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar2"), NotNull());
+ ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz2"), NotNull());
+
// Reject attribute references
- input = R"(<item name="foo2" type="id">?attr/bar"</item>)";
+ input = R"(<item name="foo3" type="id">?attr/bar"</item>)";
ASSERT_FALSE(TestParse(input));
// Reject non-references
- input = R"(<item name="foo3" type="id">0x7f010001</item>)";
+ input = R"(<item name="foo4" type="id">0x7f010001</item>)";
ASSERT_FALSE(TestParse(input));
- input = R"(<item name="foo4" type="id">@drawable/my_image</item>)";
+ input = R"(<item name="foo5" type="id">@drawable/my_image</item>)";
ASSERT_FALSE(TestParse(input));
- input = R"(<item name="foo5" type="id"><string name="biz"></string></item>)";
+ input = R"(<item name="foo6" type="id"><string name="biz"></string></item>)";
ASSERT_FALSE(TestParse(input));
// Ids that reference other resource ids cannot be public
- input = R"(<public name="foo6" type="id">@id/bar6</item>)";
+ input = R"(<public name="foo7" type="id">@id/bar7</item>)";
ASSERT_FALSE(TestParse(input));
}
diff --git a/tools/aapt2/format/binary/XmlFlattener.cpp b/tools/aapt2/format/binary/XmlFlattener.cpp
index d897941..2fe2424 100644
--- a/tools/aapt2/format/binary/XmlFlattener.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener.cpp
@@ -79,23 +79,31 @@
}
void Visit(const xml::Text* node) override {
- if (util::TrimWhitespace(node->text).empty()) {
- // Skip whitespace only text nodes.
+ std::string text = util::TrimWhitespace(node->text).to_string();
+
+ // Skip whitespace only text nodes.
+ if (text.empty()) {
return;
}
+ // Compact leading and trailing whitespace into a single space
+ if (isspace(node->text[0])) {
+ text = ' ' + text;
+ }
+ if (isspace(node->text[node->text.length() - 1])) {
+ text = text + ' ';
+ }
+
ChunkWriter writer(buffer_);
ResXMLTree_node* flat_node = writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE);
flat_node->lineNumber = util::HostToDevice32(node->line_number);
flat_node->comment.index = util::HostToDevice32(-1);
- ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();
-
// Process plain strings to make sure they get properly escaped.
- StringBuilder builder;
- builder.AppendText(node->text);
- AddString(builder.to_string(), kLowPriority, &flat_text->data);
+ text = StringBuilder(true /*preserve_spaces*/).AppendText(text).to_string();
+ ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();
+ AddString(text, kLowPriority, &flat_text->data);
writer.Finish();
}
diff --git a/tools/aapt2/format/binary/XmlFlattener_test.cpp b/tools/aapt2/format/binary/XmlFlattener_test.cpp
index 08243fe..25786b1 100644
--- a/tools/aapt2/format/binary/XmlFlattener_test.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener_test.cpp
@@ -286,6 +286,165 @@
EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
}
+TEST_F(XmlFlattenerTest, ProcessQuotes) {
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
+ R"(<root>
+ <item>Regular text</item>
+ <item>"Text in double quotes"</item>
+ <item>'Text in single quotes'</item>
+ <item>Text containing "double quotes"</item>
+ <item>Text containing 'single quotes'</item>
+ </root>)");
+
+ size_t len;
+ android::ResXMLTree tree;
+
+ XmlFlattenerOptions options;
+ ASSERT_TRUE(Flatten(doc.get(), &tree, options));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Regular text"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"\"Text in double quotes\""));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"'Text in single quotes'"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing \"double quotes\""));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing 'single quotes'"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
+}
+
+TEST_F(XmlFlattenerTest, ProcessWhitepspace) {
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
+ R"(<root>
+ <item> Compact Spaces </item>
+ <item>
+ A
+ </item>
+ <item>B </item>
+ <item>C </item>
+ <item> D </item>
+ <item> E</item>
+ <item> F</item>
+ <item> G </item>
+ <item> H </item>
+<item>
+I
+</item>
+<item>
+
+ J
+
+</item>
+ <item>
+ </item>
+ </root>)");
+
+ size_t len;
+ android::ResXMLTree tree;
+
+ XmlFlattenerOptions options;
+ ASSERT_TRUE(Flatten(doc.get(), &tree, options));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" Compact Spaces "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" A "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"B "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"C "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" D "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" E"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" F"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" G "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" H "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" I "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" J "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
+}
+
TEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index a274a8c..3f9588a 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -413,7 +413,8 @@
case SECTION_NONE:
continue;
case SECTION_FILE:
- printf(" new FileSection(%d, \"%s\"),\n", field->number(), s.args().c_str());
+ printf(" new FileSection(%d, \"%s\", %s),\n", field->number(), s.args().c_str(),
+ s.device_specific() ? "true" : "false");
break;
case SECTION_COMMAND:
printf(" new CommandSection(%d,", field->number());