Merge "Import translations. DO NOT MERGE" into qt-dev
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index d59d0e2..6bedfcd 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -263,6 +263,7 @@
"tests/e2e/Anomaly_duration_sum_e2e_test.cpp",
"tests/e2e/ConfigTtl_e2e_test.cpp",
"tests/e2e/PartialBucket_e2e_test.cpp",
+ "tests/e2e/DurationMetric_e2e_test.cpp",
"tests/shell/ShellSubscriber_test.cpp",
],
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 92aa425..ce75f78 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -273,6 +273,13 @@
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
+
+ FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
+ FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 615c7f2..96fbf7f 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -220,7 +220,7 @@
trueConditionDimensions.end()) {
for (auto& condIt : whatIt.second) {
condIt.second->onConditionChanged(
- currentUnSlicedPartCondition, eventTime);
+ currentUnSlicedPartCondition, eventTime);
}
}
}
@@ -314,7 +314,7 @@
auto condIt = whatIt.second.find(trueDim);
if (condIt != whatIt.second.end()) {
condIt->second->onConditionChanged(
- currentUnSlicedPartCondition, eventTime);
+ currentUnSlicedPartCondition, eventTime);
} else {
if (mMetric2ConditionLinks.size() == 0 ||
trueDim.contains(linkedConditionDimensionKey)) {
@@ -338,32 +338,25 @@
}
}
-void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const int64_t eventTime) {
- VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
- flushIfNeededLocked(eventTime);
-
- if (!mConditionSliced) {
- return;
- }
-
+void DurationMetricProducer::onSlicedConditionMayChangeInternalLocked(bool overallCondition,
+ const int64_t eventTimeNs) {
bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex);
if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker &&
mDimensionsInCondition.empty()) {
- onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTime);
+ onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTimeNs);
return;
}
if (changeDimTrackable && mSameConditionDimensionsInTracker &&
mMetric2ConditionLinks.size() <= 1) {
- onSlicedConditionMayChangeLocked_opt2(overallCondition, eventTime);
+ onSlicedConditionMayChangeLocked_opt2(overallCondition, eventTimeNs);
return;
}
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (auto& pair : whatIt.second) {
- pair.second->onSlicedConditionMayChange(overallCondition, eventTime);
+ pair.second->onSlicedConditionMayChange(overallCondition, eventTimeNs);
}
}
@@ -389,10 +382,10 @@
continue;
}
unique_ptr<DurationTracker> newTracker =
- whatIt.second.begin()->second->clone(eventTime);
+ whatIt.second.begin()->second->clone(eventTimeNs);
if (newTracker != nullptr) {
newTracker->setEventKey(MetricDimensionKey(newEventKey));
- newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
+ newTracker->onSlicedConditionMayChange(overallCondition, eventTimeNs);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}
@@ -418,10 +411,10 @@
if (hitGuardRailLocked(newEventKey)) {
continue;
}
- auto newTracker = whatIt.second.begin()->second->clone(eventTime);
+ auto newTracker = whatIt.second.begin()->second->clone(eventTimeNs);
if (newTracker != nullptr) {
newTracker->setEventKey(newEventKey);
- newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
+ newTracker->onSlicedConditionMayChange(overallCondition, eventTimeNs);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}
@@ -430,10 +423,61 @@
}
}
+void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const int64_t eventTime) {
+ VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
+
+ if (!mIsActive) {
+ return;
+ }
+
+ flushIfNeededLocked(eventTime);
+
+ if (!mConditionSliced) {
+ return;
+ }
+
+ onSlicedConditionMayChangeInternalLocked(overallCondition, eventTime);
+}
+
+void DurationMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs) {
+ MetricProducer::onActiveStateChangedLocked(eventTimeNs);
+
+ if (!mConditionSliced) {
+ if (ConditionState::kTrue != mCondition) {
+ return;
+ }
+
+ if (mIsActive) {
+ flushIfNeededLocked(eventTimeNs);
+ }
+
+ for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+ for (auto& pair : whatIt.second) {
+ pair.second->onConditionChanged(mIsActive, eventTimeNs);
+ }
+ }
+ } else if (mIsActive) {
+ flushIfNeededLocked(eventTimeNs);
+ onSlicedConditionMayChangeInternalLocked(mIsActive, eventTimeNs);
+ } else { // mConditionSliced == true && !mIsActive
+ for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+ for (auto& pair : whatIt.second) {
+ pair.second->onConditionChanged(mIsActive, eventTimeNs);
+ }
+ }
+ }
+}
+
void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
+
+ if (!mIsActive) {
+ return;
+ }
+
flushIfNeededLocked(eventTime);
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (auto& pair : whatIt.second) {
@@ -696,7 +740,9 @@
return;
}
- flushIfNeededLocked(event.GetElapsedTimestampNs());
+ if (mIsActive) {
+ flushIfNeededLocked(event.GetElapsedTimestampNs());
+ }
// Handles Stopall events.
if (matcherIndex == mStopAllIndex) {
@@ -767,6 +813,8 @@
}
}
+ condition = condition && mIsActive;
+
if (dimensionKeysInCondition.empty()) {
handleStartEvent(MetricDimensionKey(dimensionInWhat, DEFAULT_DIMENSION_KEY),
conditionKey, condition, event);
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index f711df2..56c9fd6 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -73,9 +73,15 @@
// Internal interface to handle condition change.
void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
+ // Internal interface to handle active state change.
+ void onActiveStateChangedLocked(const int64_t& eventTimeNs) override;
+
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
+ void onSlicedConditionMayChangeInternalLocked(bool overallCondition,
+ const int64_t eventTimeNs);
+
void onSlicedConditionMayChangeLocked_opt1(bool overallCondition, const int64_t eventTime);
void onSlicedConditionMayChangeLocked_opt2(bool overallCondition, const int64_t eventTime);
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 41000da..7a87f03 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -364,11 +364,27 @@
}
}
+void GaugeMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs) {
+ MetricProducer::onActiveStateChangedLocked(eventTimeNs);
+ if (ConditionState::kTrue != mCondition || !mIsPulled) {
+ return;
+ }
+ if (mTriggerAtomId == -1 || (mIsActive && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE)) {
+ pullAndMatchEventsLocked(eventTimeNs);
+ }
+
+}
+
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
const int64_t eventTimeNs) {
VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
- flushIfNeededLocked(eventTimeNs);
+
mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
+ if (!mIsActive) {
+ return;
+ }
+
+ flushIfNeededLocked(eventTimeNs);
if (mIsPulled && mTriggerAtomId == -1) {
pullAndMatchEventsLocked(eventTimeNs);
} // else: Push mode. No need to proactively pull the gauge data.
@@ -378,10 +394,14 @@
const int64_t eventTimeNs) {
VLOG("GaugeMetric %lld onSlicedConditionMayChange overall condition %d", (long long)mMetricId,
overallCondition);
+ mCondition = overallCondition ? ConditionState::kTrue : ConditionState::kFalse;
+ if (!mIsActive) {
+ return;
+ }
+
flushIfNeededLocked(eventTimeNs);
// If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
// pull for every dimension.
- mCondition = overallCondition ? ConditionState::kTrue : ConditionState::kFalse;
if (mIsPulled && mTriggerAtomId == -1) {
pullAndMatchEventsLocked(eventTimeNs);
} // else: Push mode. No need to proactively pull the gauge data.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 1b43d43..a612adf 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -106,6 +106,9 @@
// Internal interface to handle condition change.
void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
+ // Internal interface to handle active state change.
+ void onActiveStateChangedLocked(const int64_t& eventTimeNs) override;
+
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index d913427..8cbc9c4 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -107,7 +107,7 @@
}
mIsActive = evaluateActiveStateLocked(elapsedTimestampNs);
if (!mIsActive) {
- flushLocked(elapsedTimestampNs);
+ onActiveStateChangedLocked(elapsedTimestampNs);
}
}
@@ -143,7 +143,11 @@
}
activation->start_ns = elapsedTimestampNs;
activation->state = ActivationState::kActive;
+ bool oldActiveState = mIsActive;
mIsActive = true;
+ if (!oldActiveState) { // Metric went from not active to active.
+ onActiveStateChangedLocked(elapsedTimestampNs);
+ }
}
void MetricProducer::cancelEventActivationLocked(int deactivationTrackerIndex) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 3ddbef4..aa75761 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -132,23 +132,17 @@
// Consume the parsed stats log entry that already matched the "what" of the metric.
void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mIsActive) {
- onMatchedLogEventLocked(matcherIndex, event);
- }
+ onMatchedLogEventLocked(matcherIndex, event);
}
void onConditionChanged(const bool condition, const int64_t eventTime) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mIsActive) {
- onConditionChangedLocked(condition, eventTime);
- }
+ onConditionChangedLocked(condition, eventTime);
}
void onSlicedConditionMayChange(bool overallCondition, const int64_t eventTime) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mIsActive) {
- onSlicedConditionMayChangeLocked(overallCondition, eventTime);
- }
+ onSlicedConditionMayChangeLocked(overallCondition, eventTime);
}
bool isConditionSliced() const {
@@ -304,12 +298,18 @@
* bucket's end timestamp, than we flush up to the end of the latest full bucket; otherwise,
* we assume that we want to flush a partial bucket. The bucket start timestamp and bucket
* number are not changed by this function. This method should only be called by
- * flushIfNeededLocked or the app upgrade handler; the caller MUST update the bucket timestamp
- * and bucket number as needed.
+ * flushIfNeededLocked or flushLocked or the app upgrade handler; the caller MUST update the
+ * bucket timestamp and bucket number as needed.
*/
virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) {};
+ virtual void onActiveStateChangedLocked(const int64_t& eventTimeNs) {
+ if (!mIsActive) {
+ flushLocked(eventTimeNs);
+ }
+ }
+
// Convenience to compute the current bucket's end time, which is always aligned with the
// start time of the metric.
int64_t getCurrentBucketEndTimeNs() const {
@@ -412,6 +412,13 @@
bool mIsActive;
+ FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
+ FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index da3be06..6fc2c13 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -291,6 +291,13 @@
FRIEND_TEST(StatsLogProcessorTest,
TestActivationOnBootMultipleActivationsDifferentActivationTypes);
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
+
+ FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
+ FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
+ FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 17f2994..01362b6 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -109,7 +109,7 @@
mMaxPullDelayNs(metric.max_pull_delay_sec() > 0 ? metric.max_pull_delay_sec() * NS_PER_SEC
: StatsdStats::kPullMaxDelayNs),
mSplitBucketForAppUpgrade(metric.split_bucket_for_app_upgrade()),
- mConditionTimer(mCondition == ConditionState::kTrue, timeBaseNs) {
+ mConditionTimer(mIsActive && mCondition == ConditionState::kTrue, timeBaseNs) {
int64_t bucketSizeMills = 0;
if (metric.has_bucket()) {
bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket());
@@ -364,58 +364,98 @@
mHasGlobalBase = false;
}
-void ValueMetricProducer::onConditionChangedLocked(const bool condition,
- const int64_t eventTimeNs) {
+// Handle active state change. Active state change is treated like a condition change:
+// - drop bucket if active state change event arrives too late
+// - if condition is true, pull data on active state changes
+// - ConditionTimer tracks changes based on AND of condition and active state.
+void ValueMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs) {
bool isEventTooLate = eventTimeNs < mCurrentBucketStartTimeNs;
- if (!isEventTooLate) {
- if (mCondition == ConditionState::kUnknown) {
- // If the condition was unknown, we mark the bucket as invalid since the bucket will
- // contain partial data. For instance, the condition change might happen close to the
- // end of the bucket and we might miss lots of data.
- //
- // We still want to pull to set the base.
- invalidateCurrentBucket();
- }
-
- // Pull on condition changes.
- ConditionState newCondition = condition ? ConditionState::kTrue : ConditionState::kFalse;
- bool conditionChanged =
- (mCondition == ConditionState::kTrue && newCondition == ConditionState::kFalse)
- || (mCondition == ConditionState::kFalse && newCondition == ConditionState::kTrue);
- // We do not need to pull when we go from unknown to false.
- //
- // We also pull if the condition was already true in order to be able to flush the bucket at
- // the end if needed.
- //
- // onConditionChangedLocked might happen on bucket boundaries if this is called before
- // #onDataPulled.
- if (mIsPulled && (conditionChanged || condition)) {
- pullAndMatchEventsLocked(eventTimeNs, newCondition);
- }
-
- // When condition change from true to false, clear diff base but don't
- // reset other counters as we may accumulate more value in the bucket.
- if (mUseDiff && mCondition == ConditionState::kTrue
- && newCondition == ConditionState::kFalse) {
- resetBase();
- }
- mCondition = newCondition;
- } else {
- VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
- (long long)mCurrentBucketStartTimeNs);
- StatsdStats::getInstance().noteConditionChangeInNextBucket(mMetricId);
+ if (ConditionState::kTrue == mCondition && isEventTooLate) {
+ // Drop bucket because event arrived too late, ie. we are missing data for this bucket.
invalidateCurrentBucket();
- // Something weird happened. If we received another event in the future, the condition might
- // be wrong.
- mCondition = initialCondition(mConditionTrackerIndex);
}
- // This part should alway be called.
+ // Call parent method once we've verified the validity of current bucket.
+ MetricProducer::onActiveStateChangedLocked(eventTimeNs);
+
+ if (ConditionState::kTrue != mCondition) {
+ return;
+ }
+
+ // Pull on active state changes.
+ if (!isEventTooLate) {
+ if (mIsPulled) {
+ pullAndMatchEventsLocked(eventTimeNs, mCondition);
+ }
+ // When active state changes from true to false, clear diff base but don't
+ // reset other counters as we may accumulate more value in the bucket.
+ if (mUseDiff && !mIsActive) {
+ resetBase();
+ }
+ }
+
flushIfNeededLocked(eventTimeNs);
- mConditionTimer.onConditionChanged(mCondition, eventTimeNs);
+
+ // Let condition timer know of new active state.
+ mConditionTimer.onConditionChanged(mIsActive, eventTimeNs);
}
-void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs, ConditionState condition) {
+void ValueMetricProducer::onConditionChangedLocked(const bool condition,
+ const int64_t eventTimeNs) {
+ ConditionState newCondition = condition ? ConditionState::kTrue : ConditionState::kFalse;
+ bool isEventTooLate = eventTimeNs < mCurrentBucketStartTimeNs;
+
+ if (mIsActive) {
+ if (isEventTooLate) {
+ VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
+ (long long)mCurrentBucketStartTimeNs);
+ StatsdStats::getInstance().noteConditionChangeInNextBucket(mMetricId);
+ invalidateCurrentBucket();
+ } else {
+ if (mCondition == ConditionState::kUnknown) {
+ // If the condition was unknown, we mark the bucket as invalid since the bucket will
+ // contain partial data. For instance, the condition change might happen close to
+ // the end of the bucket and we might miss lots of data.
+ //
+ // We still want to pull to set the base.
+ invalidateCurrentBucket();
+ }
+
+ // Pull on condition changes.
+ bool conditionChanged =
+ (mCondition == ConditionState::kTrue && newCondition == ConditionState::kFalse)
+ || (mCondition == ConditionState::kFalse &&
+ newCondition == ConditionState::kTrue);
+ // We do not need to pull when we go from unknown to false.
+ //
+ // We also pull if the condition was already true in order to be able to flush the
+ // bucket at the end if needed.
+ //
+ // onConditionChangedLocked might happen on bucket boundaries if this is called before
+ // #onDataPulled.
+ if (mIsPulled && (conditionChanged || condition)) {
+ pullAndMatchEventsLocked(eventTimeNs, newCondition);
+ }
+
+ // When condition change from true to false, clear diff base but don't
+ // reset other counters as we may accumulate more value in the bucket.
+ if (mUseDiff && mCondition == ConditionState::kTrue
+ && newCondition == ConditionState::kFalse) {
+ resetBase();
+ }
+ }
+ }
+
+ mCondition = isEventTooLate ? initialCondition(mConditionTrackerIndex) : newCondition;
+
+ if (mIsActive) {
+ flushIfNeededLocked(eventTimeNs);
+ mConditionTimer.onConditionChanged(mCondition, eventTimeNs);
+ }
+}
+
+void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs,
+ ConditionState condition) {
vector<std::shared_ptr<LogEvent>> allData;
if (!mPullerManager->Pull(mPullTagId, &allData)) {
ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index de01e72..739f6ef 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -93,6 +93,9 @@
android::util::ProtoOutputStream* protoOutput) override;
void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
+ // Internal interface to handle active state change.
+ void onActiveStateChangedLocked(const int64_t& eventTimeNs) override;
+
// Internal interface to handle condition change.
void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
new file mode 100644
index 0000000..5da0fca
--- /dev/null
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -0,0 +1,717 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+TEST(DurationMetricE2eTest, TestOneBucket) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ auto durationPredicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = durationPredicate;
+
+ int64_t metricId = 123456;
+ auto durationMetric = config.add_duration_metric();
+ durationMetric->set_id(metricId);
+ durationMetric->set_what(durationPredicate.id());
+ durationMetric->set_bucket(FIVE_MINUTES);
+ durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+
+
+ const int64_t baseTimeNs = 0; // 0:00
+ const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
+ const int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+
+ std::unique_ptr<LogEvent> event;
+
+ // Screen is off at start of bucket.
+ event = CreateScreenStateChangedEvent(
+ android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
+ processor->OnLogEvent(event.get());
+
+ // Turn screen on.
+ const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+ processor->OnLogEvent(event.get());
+
+ // Turn off screen 30 seconds after turning on.
+ const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+ processor->OnLogEvent(event.get());
+
+ event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
+ processor->OnLogEvent(event.get());
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
+ ADB_DUMP, FAST, &buffer); // 5:01
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStartEndTimestamp(&reports);
+ EXPECT_EQ(1, reports.reports_size());
+ EXPECT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+ EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+
+ const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+ reports.reports(0).metrics(0).duration_metrics();
+ EXPECT_EQ(1, durationMetrics.data_size());
+
+ auto data = durationMetrics.data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
+ EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+ EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestTwoBuckets) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ auto durationPredicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = durationPredicate;
+
+ int64_t metricId = 123456;
+ auto durationMetric = config.add_duration_metric();
+ durationMetric->set_id(metricId);
+ durationMetric->set_what(durationPredicate.id());
+ durationMetric->set_bucket(FIVE_MINUTES);
+ durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+
+
+ const int64_t baseTimeNs = 0; // 0:00
+ const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
+ const int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+
+ std::unique_ptr<LogEvent> event;
+
+ // Screen is off at start of bucket.
+ event = CreateScreenStateChangedEvent(
+ android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
+ processor->OnLogEvent(event.get());
+
+ // Turn screen on.
+ const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+ processor->OnLogEvent(event.get());
+
+ // Turn off screen 30 seconds after turning on.
+ const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+ processor->OnLogEvent(event.get());
+
+ event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
+ processor->OnLogEvent(event.get());
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false, true,
+ ADB_DUMP, FAST, &buffer); // 10:01
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStartEndTimestamp(&reports);
+ EXPECT_EQ(1, reports.reports_size());
+ EXPECT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+ EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+
+ const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+ reports.reports(0).metrics(0).duration_metrics();
+ EXPECT_EQ(1, durationMetrics.data_size());
+
+ auto data = durationMetrics.data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(0, bucketInfo.bucket_num());
+ EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
+ EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestWithActivation) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ auto crashMatcher = CreateProcessCrashAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ *config.add_atom_matcher() = screenOffMatcher;
+ *config.add_atom_matcher() = crashMatcher;
+
+ auto durationPredicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = durationPredicate;
+
+ int64_t metricId = 123456;
+ auto durationMetric = config.add_duration_metric();
+ durationMetric->set_id(metricId);
+ durationMetric->set_what(durationPredicate.id());
+ durationMetric->set_bucket(FIVE_MINUTES);
+ durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+
+ auto metric_activation1 = config.add_metric_activation();
+ metric_activation1->set_metric_id(metricId);
+ auto event_activation1 = metric_activation1->add_event_activation();
+ event_activation1->set_atom_matcher_id(crashMatcher.id());
+ event_activation1->set_ttl_seconds(30); // 30 secs.
+
+ const int64_t bucketStartTimeNs = 10000000000;
+ const int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ sp<UidMap> m = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> subscriberAlarmMonitor;
+ vector<int64_t> activeConfigsBroadcast;
+
+ int broadcastCount = 0;
+ StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+ bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+ [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+ const vector<int64_t>& activeConfigs) {
+ broadcastCount++;
+ EXPECT_EQ(broadcastUid, uid);
+ activeConfigsBroadcast.clear();
+ activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+ activeConfigs.begin(), activeConfigs.end());
+ return true;
+ });
+
+ processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); // 0:00
+
+ EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+ sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ auto& eventActivationMap = metricProducer->mEventActivationMap;
+
+ EXPECT_FALSE(metricsManager->isActive());
+ EXPECT_FALSE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap.size(), 1u);
+ EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+ EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+ EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+ EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ std::unique_ptr<LogEvent> event;
+
+ // Turn screen off.
+ event = CreateScreenStateChangedEvent(
+ android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
+ processor.OnLogEvent(event.get());
+
+ // Turn screen on.
+ const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+ processor.OnLogEvent(event.get());
+
+ // Activate metric.
+ const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
+ const int64_t activationEndNs =
+ activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
+ event = CreateAppCrashEvent(111, activationStartNs);
+ processor.OnLogEvent(event.get());
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+ EXPECT_EQ(broadcastCount, 1);
+ EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+ EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+ EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+ EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
+ EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ // Expire activation.
+ const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
+ event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
+ processor.OnLogEvent(event.get());
+ EXPECT_FALSE(metricsManager->isActive());
+ EXPECT_FALSE(metricProducer->mIsActive);
+ EXPECT_EQ(broadcastCount, 2);
+ EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+ EXPECT_EQ(eventActivationMap.size(), 1u);
+ EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+ EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+ EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
+ EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ // Turn off screen 10 seconds after activation expiration.
+ const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+ processor.OnLogEvent(event.get());
+
+ // Turn screen on.
+ const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
+ processor.OnLogEvent(event.get());
+
+ // Turn off screen.
+ const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
+ processor.OnLogEvent(event.get());
+
+ // Activate metric.
+ const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
+ const int64_t activation2EndNs =
+ activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
+ event = CreateAppCrashEvent(211, activation2StartNs);
+ processor.OnLogEvent(event.get());
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+ EXPECT_EQ(broadcastCount, 3);
+ EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+ EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+ EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+ EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
+ EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
+ ADB_DUMP, FAST, &buffer); // 5:01
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStartEndTimestamp(&reports);
+ EXPECT_EQ(1, reports.reports_size());
+ EXPECT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+ EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+
+ const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+ reports.reports(0).metrics(0).duration_metrics();
+ EXPECT_EQ(1, durationMetrics.data_size());
+
+ auto data = durationMetrics.data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(0, bucketInfo.bucket_num());
+ EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestWithCondition) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+ *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+
+ auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+ *config.add_predicate() = holdingWakelockPredicate;
+
+ auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+ *config.add_predicate() = isInBackgroundPredicate;
+
+ auto durationMetric = config.add_duration_metric();
+ durationMetric->set_id(StringToId("WakelockDuration"));
+ durationMetric->set_what(holdingWakelockPredicate.id());
+ durationMetric->set_condition(isInBackgroundPredicate.id());
+ durationMetric->set_aggregation_type(DurationMetric::SUM);
+ durationMetric->set_bucket(FIVE_MINUTES);
+
+ ConfigKey cfgKey;
+ uint64_t bucketStartTimeNs = 10000000000;
+ uint64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ auto& eventActivationMap = metricProducer->mEventActivationMap;
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+ EXPECT_TRUE(eventActivationMap.empty());
+
+ int appUid = 123;
+ std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+
+ auto event = CreateAcquireWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+ processor->OnLogEvent(event.get());
+
+ event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+ processor->OnLogEvent(event.get());
+
+ event = CreateMoveToForegroundEvent(
+ appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+ processor->OnLogEvent(event.get());
+
+ event = CreateReleaseWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 4 * 60 * NS_PER_SEC); // 4:00
+ processor->OnLogEvent(event.get());
+
+ vector<uint8_t> buffer;
+ ConfigMetricsReportList reports;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+ ADB_DUMP, FAST, &buffer);
+ EXPECT_GT(buffer.size(), 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStringInReport(&reports);
+ backfillStartEndTimestamp(&reports);
+
+ EXPECT_EQ(1, reports.reports_size());
+ EXPECT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+ auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+
+ // Validate bucket info.
+ EXPECT_EQ(1, data.bucket_info_size());
+
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ((2 * 60 + 53) * NS_PER_SEC, bucketInfo.duration_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+ *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+
+ auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+ // The predicate is dimensioning by first attribution node by uid.
+ FieldMatcher dimensions = CreateAttributionUidDimensions(
+ android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
+ *config.add_predicate() = holdingWakelockPredicate;
+
+ auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+ *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+ CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+ *config.add_predicate() = isInBackgroundPredicate;
+
+ auto durationMetric = config.add_duration_metric();
+ durationMetric->set_id(StringToId("WakelockDuration"));
+ durationMetric->set_what(holdingWakelockPredicate.id());
+ durationMetric->set_condition(isInBackgroundPredicate.id());
+ durationMetric->set_aggregation_type(DurationMetric::SUM);
+ // The metric is dimensioning by first attribution node and only by uid.
+ *durationMetric->mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ durationMetric->set_bucket(FIVE_MINUTES);
+
+ // Links between wakelock state atom and condition of app is in background.
+ auto links = durationMetric->add_links();
+ links->set_condition(isInBackgroundPredicate.id());
+ auto dimensionWhat = links->mutable_fields_in_what();
+ dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+ dimensionWhat->add_child()->set_field(1); // uid field.
+ *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
+ android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
+
+ ConfigKey cfgKey;
+ uint64_t bucketStartTimeNs = 10000000000;
+ uint64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ auto& eventActivationMap = metricProducer->mEventActivationMap;
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+ EXPECT_TRUE(eventActivationMap.empty());
+
+ int appUid = 123;
+ std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+
+ auto event = CreateAcquireWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+ processor->OnLogEvent(event.get());
+
+ event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+ processor->OnLogEvent(event.get());
+
+ event = CreateReleaseWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 60 * NS_PER_SEC); // 1:00
+ processor->OnLogEvent(event.get());
+
+
+ event = CreateMoveToForegroundEvent(
+ appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+ processor->OnLogEvent(event.get());
+
+ vector<uint8_t> buffer;
+ ConfigMetricsReportList reports;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+ ADB_DUMP, FAST, &buffer);
+ EXPECT_GT(buffer.size(), 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStringInReport(&reports);
+ backfillStartEndTimestamp(&reports);
+
+ EXPECT_EQ(1, reports.reports_size());
+ EXPECT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+ auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+ // Validate dimension value.
+ ValidateAttributionUidDimension(data.dimensions_in_what(),
+ android::util::WAKELOCK_STATE_CHANGED, appUid);
+ // Validate bucket info.
+ EXPECT_EQ(1, data.bucket_info_size());
+
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+ *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+
+ auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+ // The predicate is dimensioning by first attribution node by uid.
+ FieldMatcher dimensions = CreateAttributionUidDimensions(
+ android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
+ *config.add_predicate() = holdingWakelockPredicate;
+
+ auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+ *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+ CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+ *config.add_predicate() = isInBackgroundPredicate;
+
+ auto durationMetric = config.add_duration_metric();
+ durationMetric->set_id(StringToId("WakelockDuration"));
+ durationMetric->set_what(holdingWakelockPredicate.id());
+ durationMetric->set_condition(isInBackgroundPredicate.id());
+ durationMetric->set_aggregation_type(DurationMetric::SUM);
+ // The metric is dimensioning by first attribution node and only by uid.
+ *durationMetric->mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ durationMetric->set_bucket(FIVE_MINUTES);
+
+ // Links between wakelock state atom and condition of app is in background.
+ auto links = durationMetric->add_links();
+ links->set_condition(isInBackgroundPredicate.id());
+ auto dimensionWhat = links->mutable_fields_in_what();
+ dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+ dimensionWhat->add_child()->set_field(1); // uid field.
+ *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
+ android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
+
+ auto metric_activation1 = config.add_metric_activation();
+ metric_activation1->set_metric_id(durationMetric->id());
+ auto event_activation1 = metric_activation1->add_event_activation();
+ event_activation1->set_atom_matcher_id(screenOnMatcher.id());
+ event_activation1->set_ttl_seconds(60 * 2); // 2 minutes.
+
+ ConfigKey cfgKey;
+ uint64_t bucketStartTimeNs = 10000000000;
+ uint64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ auto& eventActivationMap = metricProducer->mEventActivationMap;
+ EXPECT_FALSE(metricsManager->isActive());
+ EXPECT_FALSE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap.size(), 1u);
+ EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
+ EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+ EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+ EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ int appUid = 123;
+ std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+
+ auto event = CreateAcquireWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+ processor->OnLogEvent(event.get());
+ EXPECT_FALSE(metricsManager->isActive());
+ EXPECT_FALSE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+ EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+ EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+ processor->OnLogEvent(event.get());
+ EXPECT_FALSE(metricsManager->isActive());
+ EXPECT_FALSE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+ EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+ EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC; // 0:30
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+ processor->OnLogEvent(event.get());
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
+ EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
+ EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ const int64_t durationEndNs =
+ durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC; // 3:00
+ event = CreateAppCrashEvent(333, durationEndNs);
+ processor->OnLogEvent(event.get());
+ EXPECT_FALSE(metricsManager->isActive());
+ EXPECT_FALSE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+ EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
+ EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ event = CreateMoveToForegroundEvent(
+ appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+ processor->OnLogEvent(event.get());
+
+ event = CreateReleaseWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC); // 4:17
+ processor->OnLogEvent(event.get());
+
+ event = CreateMoveToBackgroundEvent(
+ appUid, bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC); // 4:20
+ processor->OnLogEvent(event.get());
+
+ event = CreateAcquireWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC); // 4:25
+ processor->OnLogEvent(event.get());
+
+ const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC; // 4:30
+ event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
+ processor->OnLogEvent(event.get());
+ EXPECT_TRUE(metricsManager->isActive());
+ EXPECT_TRUE(metricProducer->mIsActive);
+ EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
+ EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
+ EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+
+ vector<uint8_t> buffer;
+ ConfigMetricsReportList reports;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+ ADB_DUMP, FAST, &buffer);
+ EXPECT_GT(buffer.size(), 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStringInReport(&reports);
+ backfillStartEndTimestamp(&reports);
+
+ EXPECT_EQ(1, reports.reports_size());
+ EXPECT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+ auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+ // Validate dimension value.
+ ValidateAttributionUidDimension(data.dimensions_in_what(),
+ android::util::WAKELOCK_STATE_CHANGED, appUid);
+ // Validate bucket info.
+ EXPECT_EQ(2, data.bucket_info_size());
+
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
+
+ bucketInfo = data.bucket_info(1);
+ EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 6ec0a11..c7ba9be 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -446,22 +446,23 @@
// Pulling alarm arrives on time and reset the sequential pulling alarm.
// Event should not be kept.
- processor->informPullAlarmFired(nextPullTimeNs + 1);
+ processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+ // Activate the metric. A pull occurs upon activation.
const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
- processor->OnLogEvent(batterySaverOnEvent.get());
+ processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
- // This event should be kept. 1 total.
- processor->informPullAlarmFired(nextPullTimeNs + 1);
+ // This event should be kept. 2 total.
+ processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
nextPullTimeNs);
- // This event should be kept. 2 total.
- processor->informPullAlarmFired(nextPullTimeNs + 2);
+ // This event should be kept. 3 total.
+ processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
// Create random event to deactivate metric.
@@ -469,7 +470,7 @@
processor->OnLogEvent(deactivationEvent.get());
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
- // Event should not be kept. 2 total.
+ // Event should not be kept. 3 total.
processor->informPullAlarmFired(nextPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
@@ -497,27 +498,39 @@
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- EXPECT_EQ(2, data.bucket_info_size());
+ EXPECT_EQ(3, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).atom_size());
- EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, data.bucket_info(0).elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(1, bucketInfo.atom_size());
+ EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+ EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
+ EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+ EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+ EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
- EXPECT_EQ(1, data.bucket_info(1).atom_size());
- EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, data.bucket_info(1).elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, data.bucket_info(1).wall_clock_timestamp_nanos_size());
+ bucketInfo = data.bucket_info(1);
+ EXPECT_EQ(1, bucketInfo.atom_size());
+ EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+ EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
+ EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+ EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+ EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+
+ bucketInfo = data.bucket_info(2);
+ EXPECT_EQ(1, bucketInfo.atom_size());
+ EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+ EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
+ EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
- data.bucket_info(1).start_bucket_elapsed_nanos());
+ bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
- data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+ bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+ EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition) {
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index ff6af38..fb878dc7 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -306,18 +306,20 @@
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
// Pulling alarm arrives on time and reset the sequential pulling alarm.
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
+ processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
+ EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+ // Activate the metric. A pull occurs here
const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
- processor->OnLogEvent(batterySaverOnEvent.get());
+ processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
+ processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
+ processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
// Create random event to deactivate metric.
@@ -325,10 +327,11 @@
processor->OnLogEvent(deactivationEvent.get());
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
+ processor->informPullAlarmFired(expectedPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
+ processor->informPullAlarmFired(expectedPullTimeNs + 4);
+ EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
@@ -352,12 +355,18 @@
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- // We have 1 full bucket, the two surrounding the activation are dropped.
- EXPECT_EQ(1, data.bucket_info_size());
+ // We have 2 full buckets, the two surrounding the activation are dropped.
+ EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(0).values_size());
+ auto bucketInfo = data.bucket_info(0);
+ EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ(1, bucketInfo.values_size());
+
+ bucketInfo = data.bucket_info(1);
+ EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+ EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+ EXPECT_EQ(1, bucketInfo.values_size());
}
#else
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cb939f0..e08f4a2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -727,6 +727,7 @@
INSTALL_ENABLE_ROLLBACK,
INSTALL_ALLOW_DOWNGRADE,
INSTALL_STAGED,
+ INSTALL_DRY_RUN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -904,6 +905,14 @@
*/
public static final int INSTALL_STAGED = 0x00200000;
+ /**
+ * Flag parameter for {@link #installPackage} to indicate that package should only be verified
+ * but not installed.
+ *
+ * @hide
+ */
+ public static final int INSTALL_DRY_RUN = 0x00800000;
+
/** @hide */
@IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
DONT_KILL_APP
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 3ea3bbc..d42478e5 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -407,7 +407,7 @@
*/
String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";
- if (useUsapPool && mUsapPoolEnabled && isValidUsapCommand(args)) {
+ if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) {
try {
return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
} catch (IOException ex) {
@@ -498,13 +498,21 @@
* @param args Zygote/USAP command arguments
* @return True if the command can be passed to a USAP; false otherwise
*/
- private static boolean isValidUsapCommand(ArrayList<String> args) {
+ private static boolean canAttemptUsap(ArrayList<String> args) {
for (String flag : args) {
for (String badFlag : INVALID_USAP_FLAGS) {
if (flag.startsWith(badFlag)) {
return false;
}
}
+ if (flag.startsWith("--nice-name=")) {
+ // Check if the wrap property is set, usap would ignore it.
+ String niceName = flag.substring(12);
+ String property_value = SystemProperties.get("wrap." + niceName);
+ if (property_value != null && property_value.length() != 0) {
+ return false;
+ }
+ }
}
return true;
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 1b0a458..48ca766 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -106,13 +106,6 @@
*/
public static final String HASH_SALT_MAX_DAYS = "hash_salt_max_days";
- // Flag related to Privacy Indicators
-
- /**
- * Whether the Permissions Hub is showing.
- */
- public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
-
// Flags related to Assistant Handles
/**
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 24ad751..392f074 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -28,7 +28,6 @@
import java.io.File;
import java.io.FilenameFilter;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -138,11 +137,12 @@
if (!dedup.isEmpty()) {
mFileNumbers.addAll(dedup);
Collections.sort(mFileNumbers);
+ setActiveFile(mFileNumbers.get(mFileNumbers.size() - 1));
} else {
// No file found, default to have file 0.
mFileNumbers.add(0);
+ setActiveFile(0);
}
- createActiveFile();
}
/**
@@ -157,22 +157,15 @@
mHistoryBuffer = historyBuffer;
}
/**
- * The highest numbered history file is active file that mHistoryBuffer is backed up into.
- * If file does not exists, truncate() creates a empty file.
+ * Set the active file that mHistoryBuffer is backed up into.
+ *
+ * @param fileNumber the history file that mHistoryBuffer is backed up into.
*/
- private void createActiveFile() {
- final AtomicFile file = getFile(mFileNumbers.get(mFileNumbers.size() - 1));
+ private void setActiveFile(int fileNumber) {
+ mActiveFile = getFile(fileNumber);
if (DEBUG) {
- Slog.d(TAG, "activeHistoryFile:" + file.getBaseFile().getPath());
+ Slog.d(TAG, "activeHistoryFile:" + mActiveFile.getBaseFile().getPath());
}
- if (!file.exists()) {
- try {
- file.truncate();
- } catch (IOException e) {
- Slog.e(TAG, "Error creating history file "+ file.getBaseFile().getPath(), e);
- }
- }
- mActiveFile = file;
}
/**
@@ -189,7 +182,7 @@
* When {@link #mHistoryBuffer} reaches {@link BatteryStatsImpl.Constants#MAX_HISTORY_BUFFER},
* create next history file.
*/
- public void createNextFile() {
+ public void startNextFile() {
if (mFileNumbers.isEmpty()) {
Slog.wtf(TAG, "mFileNumbers should never be empty");
return;
@@ -198,7 +191,7 @@
// number plus one.
final int next = mFileNumbers.get(mFileNumbers.size() - 1) + 1;
mFileNumbers.add(next);
- createActiveFile();
+ setActiveFile(next);
// if free disk space is less than 100MB, delete oldest history file.
if (!hasFreeDiskSpace()) {
@@ -224,7 +217,7 @@
}
mFileNumbers.clear();
mFileNumbers.add(0);
- createActiveFile();
+ setActiveFile(0);
}
/**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index c04a249..e52f8e1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3685,7 +3685,7 @@
Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
+ (SystemClock.uptimeMillis() - start));
}
- mBatteryStatsHistory.createNextFile();
+ mBatteryStatsHistory.startNextFile();
mHistoryBuffer.setDataSize(0);
mHistoryBuffer.setDataPosition(0);
mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 69a7c4d..a67cb34 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -258,7 +258,7 @@
} else if (base::StartsWith(name, "[anon:libc_malloc]")) {
which_heap = HEAP_NATIVE;
} else if (base::StartsWith(name, "[stack")) {
- which_heap = HEAP_NATIVE;
+ which_heap = HEAP_STACK;
} else if (base::EndsWith(name, ".so")) {
which_heap = HEAP_SO;
is_swappable = true;
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ebd79b2..6fb2986 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"የመሞከሪያ ጥቅል ሁነታን ለማሰናከል የፋብሪካ ዳግም ቅንብርን ይሞክሩ።"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"በዩኤስቢ ወደብ ውስጥ ፈሳሽ ወይም ፍርስራሽ"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"የዩኤስቢ ወደብ በራስ-ሰር ተሰናክሏል። የበለጠ ለመረዳት መታ ያድርጉ።"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"የዩኤስቢ ወደቡን መጠቀም ችግር የለውም"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ስልክ ከእንግዲህ ፈሳሽ ወይም ፍርስራሽ አላገኘም።"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"የሳንካ ሪፖርትን በመውሰድ ላይ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"የሳንካ ሪፖርት ይጋራ?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"ቀጣዩን አግኝ"</string>
<string name="find_previous" msgid="2196723669388360506">"ቀዳሚውን አግኝ"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"የስፍራ ጥየቃ ቅፅ<xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"የስፍራ ጥየቃ"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"የአካባቢ ጥየቃ"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">" በ፡<xliff:g id="NAME">%1$s</xliff:g>(<xliff:g id="SERVICE">%2$s</xliff:g>) ተጠየቀ"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"አዎ"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"አይ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 99f3747..29c155d 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -700,7 +700,7 @@
<item msgid="1103601433382158155">"فاكس العمل"</item>
<item msgid="1735177144948329370">"فاكس المنزل"</item>
<item msgid="603878674477207394">"جهاز نداء"</item>
- <item msgid="1650824275177931637">"آخر"</item>
+ <item msgid="1650824275177931637">"غير ذلك"</item>
<item msgid="9192514806975898961">"مخصص"</item>
</string-array>
<string-array name="emailAddressTypes">
@@ -1201,7 +1201,7 @@
<string name="no" msgid="5141531044935541497">"إلغاء"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"تنبيه"</string>
<string name="loading" msgid="7933681260296021180">"جارٍ التحميل…"</string>
- <string name="capital_on" msgid="1544682755514494298">"تشغيل"</string>
+ <string name="capital_on" msgid="1544682755514494298">"مفعّلة"</string>
<string name="capital_off" msgid="6815870386972805832">"إيقاف"</string>
<string name="whichApplication" msgid="4533185947064773386">"إكمال الإجراء باستخدام"</string>
<string name="whichApplicationNamed" msgid="8260158865936942783">"إكمال الإجراء باستخدام %1$s"</string>
@@ -1445,8 +1445,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"يمكنك إجراء إعادة ضبط على إعدادات المصنع لإيقاف وضع \"مفعِّل اختبار\"."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"السوائل والشوائب في منفذ USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"تمّ إيقاف منفذ USB تلقائيًا. انقُر لمعرفة المزيد من المعلومات."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"مسموح باستخدام منفذ USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"لم يَعُد الهاتف يكتشف سوائل أو شوائب."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"جارٍ الحصول على تقرير الخطأ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"هل تريد مشاركة تقرير الخطأ؟"</string>
@@ -1586,7 +1585,7 @@
<string name="find_next" msgid="5742124618942193978">"بحث عن التطابق التالي"</string>
<string name="find_previous" msgid="2196723669388360506">"بحث عن التطابق السابق"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"طلب الموقع من <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"طلب الموقع"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"طلب الموقع الجغرافي"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"مطلوب من <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"نعم"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"لا"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index b44f052..14f626d 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"টেষ্ট হাৰনেছ ম’ড অক্ষম কৰিবলৈ ফেক্টৰী ৰিছেট কৰক।"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"ইউএছবি প’ৰ্টত তৰল বা ধূলি-মাকতি আছে"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"ইউএছবি প’ৰ্ট স্বয়ংক্ৰিয়ভাৱে অক্ষম কৰা হয়। অধিক জানিবৰ বাবে টিপক।"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"ইউএছবি প’ৰ্ট ব্যৱহাৰ কৰাত সমস্যা নাই"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ফ’নটোৱে তৰল বা ধূলি-মাকতি আৰু চিনাক্ত নকৰে।"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"বাগ সম্পর্কীয় অভিযোগ গ্ৰহণ কৰি থকা হৈছে…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰিবনে?"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 38e93d9..b8e11f2 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Test Rejimini deaktiv etmək üçün fabrika ayarlarına sıfırlayın."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB portuna maye sızıb və ya qırılıb"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB portu avtomatik deaktiv edildi. Ətraflı məlumat üçün klikləyin."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB portundan istifadə etmək üçün OK"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon artıq maye və ya nasazlığı aşkarlamayacaq."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabatı verilir..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 5539515..5285e8e 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1379,8 +1379,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Obavite resetovanje na fabrička podešavanja da biste onemogućili režim probnog korišćenja."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Tečnost ili nečistoća u USB portu"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB port je automatski isključen. Dodirnite da biste saznali više."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Korišćenje USB porta je dozvoljeno"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon više ne otkriva tečnost ili nečistoću."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izveštaj o grešci se generiše…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li da podelite izveštaj o grešci?"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 5705e616..1093420 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Каб выключыць тэставы рэжым, скіньце налады да заводскіх значэнняў."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Вадкасць або смецце ў порце USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Порт USB аўтаматычна адключаны. Каб даведацца больш, націсніце тут."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Порт USB можна выкарыстоўваць"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Тэлефон выявіў, што вадкасці і смецця больш няма."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Стварэнне справаздачы пра памылку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Падзяліцца справаздачай пра памылку?"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 4027f03..e1f055e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Възстановете фабричните настройки, за да деактивирате режима за тестова среда."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Течност или замърсяване в USB порта"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB портът е деактивиран автоматично. Докоснете, за да научите повече."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Можете да използвате USB порта"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Телефонът вече не открива течности или замърсяване."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Сигналът за програмна грешка се извлича…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели ли сигналът за програмна грешка?"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index dbe3cd2..39c8368 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"টেস্ট হারনেস মোড বন্ধ করতে ফ্যাক্টরি রিসেট করুন।"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"ইউএসবি পোর্টে তরল পদার্থ অথবা ধুলো কণা"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"ইউএসবি পোর্ট নিজে থেকে বন্ধ করা হবে। আরও জানতে ট্যাপ করুন।"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"ইউএসবি পোর্ট ব্যবহার করা যেতে পারে"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ফোন আর তরল পদার্থ এবং ধুলো কণা শনাক্ত করবে না।"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ত্রুটির প্রতিবেদন নেওয়া হচ্ছে..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ত্রুটির প্রতিবেদন শেয়ার করবেন?"</string>
@@ -1495,7 +1494,7 @@
<string name="find_next" msgid="5742124618942193978">"পরবর্তীটি খুঁজুন"</string>
<string name="find_previous" msgid="2196723669388360506">"পূর্ববর্তীটি খুঁজুন"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> এর থেকে অবস্থানের অনুরোধ"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"অবস্থানের অনুরোধ"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"লোকেশন জানার অনুরোধ"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) এর দ্বারা অনুরোধকৃত"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"হ্যাঁ"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"না"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index fb1b1b0..3d61c15 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1381,8 +1381,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Izvršite vraćanje na fabričke postavke da onemogućite način rada okvira za testiranje."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Tečnost ili nečistoće u USB priključku"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB priključak je automatski onemogućen. Dodirnite da saznate više."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB priključak je sada sigurno koristiti"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon više ne detektira tečnost ili nečistoće."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Prijem izvještaja o grešci..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Podijeliti izvještaj o grešci?"</string>
@@ -1519,7 +1518,7 @@
<string name="find_next" msgid="5742124618942193978">"Nađi sljedeći"</string>
<string name="find_previous" msgid="2196723669388360506">"Nađi prethodni"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Korisnik <xliff:g id="NAME">%s</xliff:g> je poslao zahtjev za utvrđivanje lokacije"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Zahtjev za utvrđivanje lokacije"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Zahtjev za lokaciju"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Zahtjev uputio <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Da"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Ne"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f94fcbb..4dcab77 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Si vols desactivar el mode Agent de prova, restableix les dades de fàbrica."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Hi ha líquid o pols al port USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"El port USB es desactiva automàticament. Toca per obtenir més informació."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Ja pots utilitzar el port USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"El telèfon ja no detecta líquids ni pols."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"S\'està creant l\'informe d\'errors…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vols compartir l\'informe d\'errors?"</string>
@@ -1783,7 +1782,7 @@
<string name="restr_pin_try_later" msgid="973144472490532377">"Torna-ho a provar més tard"</string>
<string name="immersive_cling_title" msgid="8394201622932303336">"Mode de pantalla completa"</string>
<string name="immersive_cling_description" msgid="3482371193207536040">"Per sortir, llisca cap avall des de la part superior."</string>
- <string name="immersive_cling_positive" msgid="5016839404568297683">"D\'acord"</string>
+ <string name="immersive_cling_positive" msgid="5016839404568297683">"Entesos"</string>
<string name="done_label" msgid="2093726099505892398">"Fet"</string>
<string name="hour_picker_description" msgid="6698199186859736512">"Control circular de les hores"</string>
<string name="minute_picker_description" msgid="8606010966873791190">"Control circular dels minuts"</string>
@@ -2005,7 +2004,7 @@
<string name="battery_saver_off_notification_summary" msgid="1374222493681267143">"L\'estalvi de bateria s\'ha desactivat. Les funcions ja no estan restringides."</string>
<string name="battery_saver_off_alternative_notification_summary" msgid="4340727818546508436">"L\'estalvi de bateria s\'ha desactivat. Les funcions ja no estan restringides."</string>
<string name="mime_type_folder" msgid="7111951698626315204">"Carpeta"</string>
- <string name="mime_type_apk" msgid="5518003630972506900">"Aplicació per a Android"</string>
+ <string name="mime_type_apk" msgid="5518003630972506900">"Aplicació d\'Android"</string>
<string name="mime_type_generic" msgid="6833871596845900027">"Fitxer"</string>
<string name="mime_type_generic_ext" msgid="8450275970061657174">"Fitxer <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
<string name="mime_type_audio" msgid="6289777657172050926">"Àudio"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f2ed698..2e76388 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Chcete-li deaktivovat režim správce testů, restartujte zařízení do továrního nastavení."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Kapalina nebo nečistota v portu USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Port USB byl automaticky deaktivován. Klepnutím zobrazíte další informace."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Port USB lze bezpečně použít"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon již nedetekuje kapaliny ani nečistoty."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Vytváření zprávy o chybě…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Sdílet zprávu o chybě?"</string>
@@ -1540,7 +1539,7 @@
<string name="find_next" msgid="5742124618942193978">"Najít další"</string>
<string name="find_previous" msgid="2196723669388360506">"Najít předchozí"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Požadavek na informace o poloze od uživatele <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Požadavek na informace o poloze"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Žádost o informaci o poloze"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Požadavek od uživatele <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Ano"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Ne"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index c2e8f6b..6e80d02 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Gendan fabriksindstillingerne for at deaktivere tilstanden Testsele."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Væske eller snavs i USB-porten"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-porten deaktiveres automatisk. Tryk for at få flere oplysninger."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB-porten kan bruges"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefonen registrerer ikke længere væske og snavs."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Opretter fejlrapport…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele fejlrapporten?"</string>
@@ -1980,7 +1979,7 @@
<string name="harmful_app_warning_title" msgid="8982527462829423432">"Der er registreret en skadelig app"</string>
<string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> anmoder om tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7867478911006447565">"Rediger"</string>
- <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"Telefonen vil vibrere ved opkald og notifikationer"</string>
+ <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"Telefonen vibrerer ved opkald og notifikationer"</string>
<string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"Der afspilles ikke lyd ved opkald og notifikationer"</string>
<string name="notification_channel_system_changes" msgid="5072715579030948646">"Systemændringer"</string>
<string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"Forstyr ikke"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index a6e8997..83d1db4 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Setz das Gerät auf die Werkseinstellungen zurück, um den Test-Harnischmodus zu deaktivieren."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Flüssigkeiten oder Fremdkörper im USB-Port"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Der USB-Port wird automatisch deaktiviert. Für weitere Informationen tippen."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB-Port kann wieder verwendet werden"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Das Smartphone erkennt keine Flüssigkeiten oder Fremdkörper mehr."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird abgerufen…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6fef44c..50057de 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Restablece la configuración de fábrica para inhabilitar el modo de agente de prueba."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Hay líquido o suciedad en el puerto USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"El puerto USB se inhabilitó automáticamente. Presiona para obtener más información."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Se puede usar el puerto USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"El teléfono ya no detecta líquidos o suciedad."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Realizando un informe de errores…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 4a39018..433645b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Restablece los ajustes de fábrica para inhabilitar el modo de agente de prueba."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Se ha detectado líquido o suciedad en el puerto USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"El puerto USB se ha inhabilitado automáticamente. Toca para obtener más información."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Se puede utilizar el puerto USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"El teléfono ya no detecta líquidos ni suciedad."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de errores…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index d7de02f..871e92a 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Testrakendirežiimi keelamiseks taastage tehaseseaded."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB-pordis on vedelik või mustus"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-port on automaatselt keelatud. Puudutage lisateabe saamiseks."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB-porti tohib kasutada"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon ei tuvasta enam vedelikku ega mustust."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Veaaruande võtmine …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kas jagada veaaruannet?"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4ec7c1c..97584c0 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -584,7 +584,7 @@
<string name="face_error_canceled" msgid="2768146728600802422">"Utzi da aurpegi bidezko eragiketa"</string>
<string name="face_error_user_canceled" msgid="9003022830076496163">"Erabiltzaileak utzi du aurpegi bidezko autentifikazioa"</string>
<string name="face_error_lockout" msgid="3407426963155388504">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
- <string name="face_error_lockout_permanent" msgid="3485837851962070925">"Saiakera gehiegi egin dira. Desgaitu da aurpegi bidezko autentifikazioa."</string>
+ <string name="face_error_lockout_permanent" msgid="3485837851962070925">"Saiakera gehiegi egin dira. Desgaitu egin da aurpegi bidezko autentifikazioa."</string>
<string name="face_error_unable_to_process" msgid="4940944939691171539">"Ezin da egiaztatu aurpegia. Saiatu berriro."</string>
<string name="face_error_not_enrolled" msgid="2600952202843125796">"Ez duzu konfiguratu aurpegi bidezko autentifikazioa"</string>
<string name="face_error_hw_not_present" msgid="1317845121210260372">"Gailu honek ez du onartzen aurpegi bidezko autentifikazioa"</string>
@@ -612,8 +612,8 @@
<string name="permdesc_connection_manager" msgid="5925480810356483565">"Telekomunikabideekiko konexioak kudeatzea baimentzen die aplikazioei."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"erabili pantaila deiak abian direnean"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzeko aukera ematen die aplikazioei."</string>
- <string name="permlab_bind_connection_service" msgid="3557341439297014940">"elkarreragin telefono-zerbitzuekin"</string>
- <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Deiak egiteko eta jasotzeko telefonia-zerbitzuekin elkarreragitea baimentzen die aplikazioei."</string>
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"jardun interakzioan telefono-zerbitzuekin"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Deiak egiteko eta jasotzeko telefonia-zerbitzuekin interakzioan aritzea baimentzen die aplikazioei."</string>
<string name="permlab_control_incall_experience" msgid="9061024437607777619">"eskaini erabiltzaileentzako aukerak deiak abian direnean"</string>
<string name="permdesc_control_incall_experience" msgid="915159066039828124">"Deiak abian direnean erabiltzeko aukera eskaintzea baimentzen die aplikazioei."</string>
<string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"irakurri sare-erabileraren historia"</string>
@@ -969,8 +969,8 @@
<string name="searchview_description_submit" msgid="2688450133297983542">"Bidali kontsulta"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Ahozko bilaketa"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"\"Arakatu ukituta\" eginbidea gaitu nahi duzu?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo tabletarekin elkarrekintzan aritzeko keinuak egin ditzakezu."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo telefonoarekin elkarrekintzan aritzeko keinuak egin ditzakezu."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo tabletarekin interakzioan aritzeko keinuak egin ditzakezu."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo telefonoarekin interakzioan aritzeko keinuak egin ditzakezu."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Duela hilabete"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Duela hilabete baino gutxiago"</string>
<plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
@@ -1151,7 +1151,7 @@
<string name="use_a_different_app" msgid="8134926230585710243">"Erabili beste aplikazio bat"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Garbitu aplikazio lehenetsia Sistemaren ezarpenak > Aplikazioak > Deskargatutakoak atalean."</string>
<string name="chooseActivity" msgid="7486876147751803333">"Aukeratu ekintza bat"</string>
- <string name="chooseUsbActivity" msgid="6894748416073583509">"Aukeratu USB gailurako aplikazioa"</string>
+ <string name="chooseUsbActivity" msgid="6894748416073583509">"Aukeratu USB bidezko gailurako aplikazioa"</string>
<string name="noApplications" msgid="2991814273936504689">"Ez dago ekintza hori egin dezakeen aplikaziorik."</string>
<string name="aerr_application" msgid="250320989337856518">"Gelditu egin da <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
<string name="aerr_process" msgid="6201597323218674729">"Gelditu egin da <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Proba-materialaren modua desgaitzeko, berrezarri jatorrizko datuak."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Likidoa edo zikinkeriak daude USB atakan"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB ataka automatikoki desgaitu da. Informazio gehiago lortzeko, sakatu hau."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Erabiltzeko moduan dago USB ataka"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefonoak ez du hautematen likidorik edo zikinkeriarik."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Akatsen txostena sortzen…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Akatsen txostena partekatu nahi duzu?"</string>
@@ -1901,7 +1900,7 @@
<string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string>
<string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Bilatu eguneratzeak"</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"Mezu berriak dituzu"</string>
- <string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuen aplikazioa"</string>
+ <string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuetarako aplikazioa"</string>
<string name="profile_encrypted_title" msgid="4260432497586829134">"Baliteke funtzio batzuk mugatuta egotea"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Blokeatuta dago laneko profila"</string>
<string name="profile_encrypted_message" msgid="6964994232310195874">"Sakatu profila desblokeatzeko"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index deb015c..6e78670 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"برای غیرفعال کردن «حالت مجموعه دادههای تست»، بازنشانی کارخانهای کنید."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"مایعات یا خاکروبه در درگاه USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"درگاه USB بهطور خودکار غیرفعال شده است. برای اطلاعات بیشتر، ضربه بزنید."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"میتوان از درگاه USB استفاده کرد"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"تلفن دیگر وجود مایعات یا خاکروبه را تشخیص نمیدهد."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"درحال گرفتن گزارش اشکال…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"گزارش اشکال به اشتراک گذاشته شود؟"</string>
@@ -1493,8 +1492,8 @@
<string name="websearch" msgid="4337157977400211589">"جستجوی وب"</string>
<string name="find_next" msgid="5742124618942193978">"یافتن بعدی"</string>
<string name="find_previous" msgid="2196723669388360506">"یافتن قبلی"</string>
- <string name="gpsNotifTicker" msgid="5622683912616496172">"درخواست موقعیت مکانی از <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"درخواست موقعیت مکانی"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"درخواست مکان از <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"درخواست مکان"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"درخواست شده توسط <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"بله"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"نه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 8dcf338..bdcb598 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Palauta tehdasasetukset, niin voit poistaa testikehystilan käytöstä."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Nestettä tai likaa USB-portissa"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-portti poistetaan käytöstä automaattisesti. Napauta nähdäksesi lisätietoja."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB-portin käyttö on sallittu"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Puhelin ei enää havaitse nesteitä eikä likaa."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Luodaan virheraporttia…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Jaetaanko virheraportti?"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3fc57f8..cf6f3f1 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Effectuez une réinitialisation pour désactiver le mode Logiciel de test."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Liquide ou débris dans le port USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Le port USB est désactivé automatiquement. Touchez ici pour en savoir plus."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Autorisation d\'utiliser le port USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Le téléphone ne détecte plus les liquides ni les débris."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création d\'un rapport de bogue en cours..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bogue?"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 364e87b..794e2ce 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Rétablissez la configuration d\'usine pour désactiver le mode Atelier de test."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Présence de liquide ou de saletés dans le port USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Le port USB est désactivé automatiquement. Appuyez sur cette notification pour en savoir plus."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Autoriser l\'utilisation du port USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Le téléphone ne détecte plus les liquides ni les saletés."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création du rapport de bug…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bug ?"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 58212db..47d07a2 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Restablece a configuración de fábrica para desactivar o modo de axente de proba."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Hai líquido ou residuos no porto USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"O porto USB desactivouse automaticamente. Toca para obter máis información."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Pódese utilizar o porto USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"O teléfono xa non detecta líquidos nin residuos."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de erros…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Queres compartir o informe de erros?"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 9f13a9a..a64909d 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"ટેસ્ટ હાર્નેસ મોડ બંધ કરવા માટે ફૅક્ટરી રીસેટ કરો."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB પોર્ટમાં પ્રવાહી કે ધૂળ"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB પોર્ટ ઑટોમૅટિક રીતે બંધ કરવામાં આવ્યો છે. વધુ જાણવા માટે ટૅપ કરો."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB પોર્ટનો ઉપયોગ કરવો યોગ્ય છે"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ફોનને હવે કોઈ પ્રવાહી કે ધૂળ હોવાનું જણાયું નથી."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"બગ રિપોર્ટ લઈ રહ્યાં છે…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"બગ રિપોર્ટ શેર કરીએ?"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 933a024..665dff4 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"टेस्ट हार्नेस मोड बंद करने के लिए फ़ैक्ट्री रीसेट करें."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"यूएसबी पोर्ट में तरल चीज़ या कचरा है"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"यूएसबी पोर्ट अपने आप बंद हो गया है. ज़्यादा जानने के लिए टैप करें."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"यूएसबी पोर्ट का इस्तेमाल करना सुरक्षित है"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"फ़ोन अब तरल चीज़ों या कचरे की पहचान नहीं करता."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"गड़बड़ी की रिपोर्ट ली जा रही है…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"गड़बड़ी की रिपोर्ट शेयर करें?"</string>
@@ -1456,7 +1455,7 @@
<string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना को सुनने की सुविधा"</string>
<string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
- <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति देने वाली"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचना रैंकर सेवा"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"आगे ढूंढें"</string>
<string name="find_previous" msgid="2196723669388360506">"पिछला ढूंढें"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> ने जगह का अनुरोध किया गया है"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"जगह का अनुरोध किया जा रहा है"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"जगह की जानकारी मांगी जा रही है"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) द्वारा अनुरोधित"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"हां"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"नहीं"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index b55ff89..0f40dfa 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1379,8 +1379,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Vratite na tvorničke postavke da biste onemogućili način testnog okvira."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Tekućina ili prljavština u USB priključku"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB priključak automatski je onemogućen. Dodirnite da biste saznali više."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Možete koristiti USB priključak"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon više ne otkriva tekućinu ili prljavštinu."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izrada izvješća o programskoj pogrešci…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li podijeliti izvješće o programskoj pogrešci?"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 0555c06..46fa00d 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"A Tesztelési alapkörnyezet mód kikapcsolásához állítsa vissza a gyári beállításokat."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Folyadék vagy szennyeződés az USB-portban"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-port automatikusan letiltva. Koppintson, ha további információra van szüksége."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Az USB-port rendben használható"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"A telefon már nem észlel folyadékot vagy szennyeződést."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hibajelentés készítése…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Megosztja a hibajelentést?"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 0253757..f73e18d 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -280,7 +280,7 @@
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"Թույլատրե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> հավելվածին օգտագործել ձեր կոնտակտները"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Տեղորոշում"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"տեղորոշել այս սարքը"</string>
- <string name="permgrouprequest_location" msgid="3788275734953323491">"Թույլատրե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-ին օգտագործել այս սարքի տեղադրության տվյալները"</string>
+ <string name="permgrouprequest_location" msgid="3788275734953323491">"Թույլատրե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> հավելվածին օգտագործել այս սարքի տեղադրության տվյալները"</string>
<string name="permgrouprequestdetail_location" msgid="1347189607421252902">"Տեղադրության տվյալները հասանելի կլինեն հավելվածին, միայն երբ այն օգտագործելիս լինեք"</string>
<string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"<b>Միշտ</b> հասանելի դարձնե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> հավելվածին ձեր սարքի տեղադրությունը"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"Տեղադրության տվյալները հասանելի կլինեն հավելվածին, միայն երբ այն օգտագործելիս լինեք"</string>
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Թեստային ռեժիմն անջատելու համար զրոյացրեք կարգավորումները։"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB միացքում ջուր կամ աղտ է հայտնաբերվել"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB միացքն ավտոմատ անջատվել է: Հպեք՝ ավելին իմանալու համար:"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB միացքը կարող է օգտագործվել"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Հեռախոսում ջուր կամ աղտ չի հայտնաբերվել:"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Վրիպակի զեկույցի ստեղծում…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Տրամադրե՞լ վրիպակի զեկույցը:"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 9452846..322d8ff 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Núllstilltu til að slökkva á stillingu prófunarvangs."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Vökvi eða óhreinindi í USB-tengi"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-tengi er gert óvirkt sjálfkrafa. Ýttu til að fá frekari upplýsingar."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Óhætt að nota USB-tengi"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Síminn greinir ekki lengur vökva eða óhreinindi"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Tekur við villutilkynningu…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deila villutilkynningu?"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f0b17c39..1ab837f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1492,8 +1492,8 @@
<string name="websearch" msgid="4337157977400211589">"Ricerca Web"</string>
<string name="find_next" msgid="5742124618942193978">"Trova successivo"</string>
<string name="find_previous" msgid="2196723669388360506">"Trova precedente"</string>
- <string name="gpsNotifTicker" msgid="5622683912616496172">"Richiesta posizione da <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Richiesta posizione"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"Richiesta di posizione da <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Richiesta di posizione"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Richiesto da <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Sì"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"No"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 20c6aa3..edbc82d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"כדי להשבית את מצב מסגרת בדיקה צריך לאפס להגדרות היצרן."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"יש נוזלים או חלקיקים ביציאת ה-USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"יציאת ה-USB הושבתה באופן אוטומטי. יש להקיש לקבלת מידע נוסף."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"ניתן להשתמש ביציאת ה-USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"הטלפון לא מזהה יותר נוזלים וחלקיקים."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"עיבוד דוח על באג..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"האם לשתף דוח על באג?"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2fbdebc..1e345c0 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"出荷時設定にリセットしてテストハーネス モードを無効にしてください。"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB ポート内の液体やゴミ"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB ポートが自動的に無効になりました。タップして詳細をご確認ください。"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB ポートを安全に使用できます"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"液体やゴミは検出されなくなりました。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"バグレポートを取得しています…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"バグレポートを共有しますか?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"次を検索"</string>
<string name="find_previous" msgid="2196723669388360506">"前を検索"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>さんからの現在地情報リクエスト"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"現在地情報へのアクセス許可"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"現在地情報リクエスト"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g>さん(<xliff:g id="SERVICE">%2$s</xliff:g>)からのリクエスト"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"はい"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"いいえ"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 299c3e1..78af3c1 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"დააბრუნეთ ქარხნული პარამეტრები „გარემო ტესტირებისთვის“ რეჟიმის გასათიშად."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB პორტში აღმოჩენილია სითხე ან ჭუჭყი"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB პორტი ავტომატურად გათიშულია. შეეხეთ დამატებითი ინფორმაციისთვის."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"თანხმობა USB პორტის გამოყენებაზე"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ტელეფონი აღარ აღმოაჩენს სითხეს ან ჭუჭყს."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის შექმნა…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"გსურთ ხარვეზის შესახებ ანგარიშის გაზიარება?"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 9cd94fc..457d9e8 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Сынақ бағдарламасы режимін өшіру үшін зауыттық күйіне қайтарыңыз."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB портына сұйықтық немесе қоқыс кірді"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB порты автоматты түрде өшірілді. Толығырақ ақпарат алу үшін түртіңіз."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB портын пайдалана беруге болады"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Телефон бұдан былай сұйықтықты немесе қоқысты анықтамайды."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп алынуда…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Қате туралы есепті бөлісу керек пе?"</string>
@@ -1495,7 +1494,7 @@
<string name="find_next" msgid="5742124618942193978">"Келесіні табу"</string>
<string name="find_previous" msgid="2196723669388360506">"Алдыңғыны табу"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Орын туралы өтініші жіберген <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Орын туралы өтініш"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Орын туралы сұрау"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Өтініш жіберген <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Иә"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Жоқ"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 9f34532..6d5f5f7 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1359,8 +1359,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"ធ្វើការកំណត់ដូចដើមឡើងវិញ ដើម្បីបិទមុខងារប្រមូលធ្វើតេស្ត។"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"មានទឹក ឬកម្ទេចផ្សេងៗនៅក្នុងរន្ធ USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"រន្ធ USB ត្រូវបានបិទដោយស្វ័យប្រវត្តិ។ សូមចុចដើម្បីស្វែងយល់បន្ថែម។"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"អាចប្រើរន្ធ USB បាន"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ទូរសព្ទរកមិនឃើញទឹក ឬកម្ទេចផ្សេងៗទេ។"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"កំពុងទទួលយករបាយការណ៍កំហុស…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ចែករំលែករបាយការណ៍កំហុសឬ?"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 32f7eec..afdf85c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"테스트 하네스 모드를 사용 중지하려면 초기화하세요."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB 포트에서 액체 또는 이물질 감지됨"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB 포트가 자동으로 사용 중지되었습니다. 자세한 내용을 보려면 탭하세요."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB 포트를 사용해도 좋음"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"휴대전화에서 액체나 이물질이 더 이상 감지되지 않습니다."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"버그 보고서 가져오는 중..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"버그 보고서를 공유하시겠습니까?"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index f10c057..6bfd1f5 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1359,8 +1359,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Сыноо программасынын режимин өчүрүү үчүн, баштапкы жөндөөлөргө кайтарыңыз."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB портунда суюктук же урандылар бар"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB порт автоматтык түрдө өчүрүлдү. Кененирээк маалымат алуу үчүн таптап коюңуз."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB портун колдонууга болот"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Телефон суюктук менен урандыларды аныктаган жок."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Мүчүлүштүк тууралуу баяндама бөлүшүлсүнбү?"</string>
@@ -1496,7 +1495,7 @@
<string name="find_next" msgid="5742124618942193978">"Кийинкиси"</string>
<string name="find_previous" msgid="2196723669388360506">"Мурункусу"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> колдонуучусу жайгашкан жердин маалыматын сурады"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Жайгашкан жердин маалыматын суроо"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Каякта экенин билүү"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) сурады"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Ооба"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Жок"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 85957c0..f0dfab0 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"ດຳເນີນການຣີເຊັດເປັນຄ່າຈາກໂຮງງານເພື່ອປິດການນຳໃຊ້ໂໝດ Test Harness."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"ມີຂອງແຫລວ ຫຼື ເສດດິນໃນຜອດ USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"ປິດຜອດ USB ໂດຍອັດຕະໂນມັດແລ້ວ. ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"ສາມາດໃຊ້ຜອດ USB ໄດ້"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ໂທລະສັບຈະບໍ່ກວດຫາຂອງແຫລວ ຫຼື ເສດດິນອີກຕໍ່ໄປ."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ກຳລັງຂໍລາຍງານຂໍ້ຜິດພາດ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ແບ່ງປັນລາຍງານບັນຫາບໍ?"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index d1fc5fa..2c93d74 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Atkurkite gamyklinius duomenis, kad išjungtumėte testavimo sistemos režimą."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB prievade yra skysčių ar smulkių dalelių"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB prievadas automatiškai išjungtas. Palieskite, kad sužinotumėte daugiau."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Saugu naudoti USB prievadą"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefonas nebeaptinka skysčių ar smulkių dalelių."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Pateikiamas pranešimas apie riktą…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bendrinti pranešimą apie riktą?"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index efbb677..f2ef086 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1379,8 +1379,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Lai atspējotu drošības pārbaudes režīmu, veiciet rūpnīcas datu atiestatīšanu."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB pieslēgvietā ir šķidrums vai daļiņas"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB pieslēgvieta ir automātiski atspējota. Pieskarieties, lai uzzinātu vairāk."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB pieslēgvietu drīkst izmantot"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Tālrunī vairs netiek konstatēts šķidrums vai gruži."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Notiek kļūdas pārskata izveide…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vai kopīgot kļūdas pārskatu?"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index a0088a8..3dc3cf2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Извршете фабричко ресетирање за да го оневозможите режимот на рамка за тестирање."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Течност или нечистотија во USB-портата"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-портата е автоматски оневозможена. Допрете за да дознаете повеќе."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Во ред е да се користи USB-порта"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Телефонот веќе не открива течност или нечистотија."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Се зема извештајот за грешки…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели извештајот за грешки?"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 9503bf4..7c10b95 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"പരിശോധനാ സംവിധാന മോഡ് പ്രവർത്തനരഹിതമാക്കാൻ ഫാക്ടറി പുനഃക്രമീകരണം നിർവഹിക്കുക."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB പോർട്ടിൽ ദ്രാവകമോ പൊടിയോ കണ്ടെത്തി"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB പോർട്ടർ സ്വയമേവ പ്രവർത്തനരഹിതമായി. കൂടുതലറിയാൻ ടാപ്പ് ചെയ്യുക."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"ഇനി USB പോർട്ട് ഉപയോഗിക്കാം"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"നിലവിൽ ദ്രാവകമോ പൊടിയോ ഉള്ളതായി ഫോൺ കണ്ടെത്തുന്നില്ല."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നു…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ബഗ് റിപ്പോർട്ട് പങ്കിടണോ?"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 0711a80..9a5446d 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Туршилтын цогц горимыг идэвхгүй болгохын тулд үйлдвэрийн төлөвт шинэчилнэ үү."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB порт дээрх шингэн зүйл эсвэл бохирдол"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB портыг автоматаар идэвхгүй болгосон байна. Дэлгэрэнгүй мэдээлэл авахын тулд товшино уу."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB портыг ашиглахад зүгээр"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Утас шингэн зүйл эсвэл бохирдлыг илрүүлсэнгүй."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Алдааны тайланг авч байна..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Алдааны тайланг хуваалцах уу?"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 73c0b42..aff6d82 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -280,7 +280,7 @@
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला तुमचे संपर्क अॅक्सेस करू द्यायचे?"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"या डिव्हाइसच्या स्थानावर प्रवेश"</string>
- <string name="permgrouprequest_location" msgid="3788275734953323491">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला या डिव्हाइसचे स्थान अॅक्सेस करू द्यायचे?"</string>
+ <string name="permgrouprequest_location" msgid="3788275734953323491">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला या डिव्हाइसचे स्थान अॅक्सेस करू द्यायचे?"</string>
<string name="permgrouprequestdetail_location" msgid="1347189607421252902">"तुम्ही अॅप वापरत असताना अॅपला फक्त स्थानाचा अॅक्सेस असेल"</string>
<string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला <b>प्रत्येक वेळी</b> या डिव्हाइसच्या स्थानाचा अॅक्सेस द्यायचा?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"अॅप सध्या फक्त तुम्ही अॅप वापरत असतानाच स्थान अॅक्सेस करू शकते"</string>
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"टेस्ट हार्नेस मोड बंद करण्यासाठी फॅक्टरी रीसेट करा."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB पोर्ट मध्ये ओलावा किंवा धूळ आहे"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB पोर्ट आपोआप बंद होईल. अधिक जाणून घेण्यासाठी टॅप करा."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB पोर्ट वापरण्यासाठी ठीक आहे"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"फोनला धूळ किंवा ओलावा आढळला नाही."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रीपोर्ट घेत आहे..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल शेअर करायचा?"</string>
@@ -1851,7 +1850,7 @@
<string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"आठवड्याची शेवटची रात्र"</string>
<string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"आठवड्याच्या शेवटी"</string>
<string name="zen_mode_default_events_name" msgid="8158334939013085363">"इव्हेंट"</string>
- <string name="zen_mode_default_every_night_name" msgid="3012363838882944175">"निष्क्रिय आहे"</string>
+ <string name="zen_mode_default_every_night_name" msgid="3012363838882944175">"झोपताना"</string>
<string name="muted_by" msgid="5942954724562097128">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> काही ध्वनी म्यूट करत आहे"</string>
<string name="system_error_wipe_data" msgid="6608165524785354962">"आपल्या डिव्हाइसमध्ये अंतर्गत समस्या आहे आणि तुमचा फॅक्टरी डेटा रीसेट होईपर्यंत ती अस्थिर असू शकते."</string>
<string name="system_error_manufacturer" msgid="8086872414744210668">"आपल्या डिव्हाइसमध्ये अंतर्गत समस्या आहे. तपशीलांसाठी आपल्या निर्मात्याशी संपर्क साधा."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5edfc63..9651c02 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Laksanakan tetapan semula kilang untuk melumpuhkan Mod Abah-abah Ujian."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Cecair atau serpihan dalam port USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Port USB dilumpuhkan secara automatik. Ketik untuk mengetahui lebih lanjut."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"OK untuk menggunakan port USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon tidak lagi mengesan cecair atau serpihan."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan pepijat…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kongsi laporan pepijat?"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 50b3372..d190bb7 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1494,7 +1494,7 @@
<string name="find_next" msgid="5742124618942193978">"နောက်တစ်ခု ရှာဖွေရန်"</string>
<string name="find_previous" msgid="2196723669388360506">"အရင်တစ်ခု ရှာဖွေရန်"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>မှ တည်နေရာအား တောင်းခံသည်"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"တည်နေရာအား တောင်းခံသည်"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"တည်နေရာ တောင်းခံခြင်း"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)မှတောင်းခံသည်"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Yes"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"No"</string>
@@ -1888,7 +1888,7 @@
<string name="country_selection_title" msgid="2954859441620215513">"ဒေသရွေးချယ်မှု"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ဘာသာစကားအမည် ထည့်ပါ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"အကြံပြုထားသည်"</string>
- <string name="language_picker_section_all" msgid="3097279199511617537">"ဘာသာစကားများအားလုံး"</string>
+ <string name="language_picker_section_all" msgid="3097279199511617537">"ဘာသာစကားအားလုံး"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"ဒေသအားလုံး"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ရှာဖွေရန်"</string>
<string name="app_suspended_title" msgid="2075071241147969611">"အက်ပ်ကို မရရှိနိုင်ပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 58c032b..bfba2d4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Tilbakestill enheten til fabrikkstandard for å slå av Testrammeverk-modus."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Væske eller rusk i USB-porten"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-porten deaktiveres automatisk. Trykk for å finne ut mer."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Trygt å bruke USB-porten"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefonen oppdager ikke væsker eller rusk lenger."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kjører feilrapport …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele feilrapporten?"</string>
@@ -1898,7 +1897,7 @@
<string name="work_mode_off_message" msgid="5130856710614337649">"Jobbappene dine samt varsler, data og andre funksjoner i jobbprofilen din blir slått på"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Slå på"</string>
<string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Denne appen er utviklet for en eldre versjon av Android og fungerer kanskje ikke som den skal. Prøv å se etter oppdateringer, eller kontakt utvikleren."</string>
- <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Se etter oppdatering"</string>
+ <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Se etter oppdateringer"</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye meldinger"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Åpne SMS-appen for å se"</string>
<string name="profile_encrypted_title" msgid="4260432497586829134">"Enkelte funksjoner kan begrenses"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 534752a..6987b1c 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1363,8 +1363,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"परीक्षण प्याकेज मोड असक्षम पार्न फ्याक्ट्री रिसेट गर्नुहोस्।"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB पोर्टमा तरल पदार्थ वा धुलो भएको कुरा पत्ता लाग्यो"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB पोर्ट स्वतः असक्षम पारियो। थप जान्न ट्याप गर्नुहोस्।"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB पोर्ट प्रयोग गर्दा हुन्छ"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"फोनले अब उप्रान्त तरल पदार्थ वा धुलो नभएको पत्ता लगायो"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट लिँदै..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्टलाई साझेदारी गर्ने हो?"</string>
@@ -1500,7 +1499,7 @@
<string name="find_next" msgid="5742124618942193978">"अर्को भेटाउनुहोस्"</string>
<string name="find_previous" msgid="2196723669388360506">"अघिल्लो फेला पार्नुहोस्"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> बाट स्थान अनुरोध"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"स्थान अनुरोध"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"स्थानसम्बन्धी अनुरोध"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) द्वारा अनुरोध गरिएको"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"हो"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"होइन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index fe106e1..bd10cf2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Reset de fabrieksinstellingen om de test harness-modus uit te schakelen."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Vloeistof of vuil in USB-poort"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-poort is automatisch uitgeschakeld. Tik voor meer informatie."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB-poort kan worden gebruikt"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"De telefoon detecteert geen vloeistof of vuil meer."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Bugrapport genereren…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bugrapport delen?"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 7e79f21..ca16155 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"ଟେଷ୍ଟ ହାର୍ନେସ୍ ମୋଡ୍ ଅକ୍ଷମ କରିବାକୁ ଏକ ଫ୍ୟାକ୍ଟରୀ ରିସେଟ୍ କରନ୍ତୁ।"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB ପୋର୍ଟରେ ତରଳ ପଦାର୍ଥ ବା ଧୂଳି"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB ପୋର୍ଟ ସ୍ୱଚାଳିତ ଭାବେ ଅକ୍ଷମ ହୋଇଛି। ଅଧିକ ଜାଣିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB ପୋର୍ଟ ବ୍ୟବହାର କରିବା ପାଇଁ ଠିକ୍ ଅଟେ"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ଫୋନ୍ ଆଉ ତରଳ ପଦାର୍ଥ କିମ୍ବା ଧୂଳିର ଚିହ୍ନଟ କରୁନାହିଁ।"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ବଗ୍ ରିପୋର୍ଟ ନିଆଯାଉଛି…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ବଗ୍ ରିପୋର୍ଟ ସେୟାର୍ କରିବେ?"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index e6c8bfc..0f92fdd 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"ਟੈਸਟ ਹਾਰਨੈੱਸ ਮੋਡ ਬੰਦ ਕਰਨ ਲਈ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਕਰੋ।"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB ਪੋਰਟ ਵਿੱਚ ਪਾਣੀ ਜਾਂ ਧੂੜ-ਮਿੱਟੀ"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB ਪੋਰਟ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਬੰਦ ਕੀਤਾ ਗਿਆ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB ਪੋਰਟ ਵਰਤਣ ਲਈ ਠੀਕ ਹੈ"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ਫ਼ੋਨ ਹੁਣ ਪਾਣੀ ਜਾਂ ਧੂੜ-ਮਿੱਟੀ ਦਾ ਪਤਾ ਨਹੀਂ ਲਗਾਉਂਦਾ ਹੈ।"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ਬੱਗ ਰਿਪਰੋਟ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ਕੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index bcf47e0..22634e2 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Przywróć ustawienia fabryczne, by wyłączyć tryb jarzma testowego."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Wilgoć lub brud w porcie USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Port USB został automatycznie wyłączony. Kliknij, by dowiedzieć się więcej."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Możesz używać portu USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon nie wykrywa już wilgoci ani zanieczyszczeń."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zgłaszam błąd…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Udostępnić raport o błędzie?"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index fbabb34..e0047ff 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Realize uma redefinição para configuração original para desativar o modo Arcabouço de testes."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Líquido ou detrito na porta USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é desativada automaticamente. Toque para saber mais."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro usar a porta USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Não há mais líquidos ou detritos detectados no smartphone."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"Localizar próximo"</string>
<string name="find_previous" msgid="2196723669388360506">"Localizar anterior"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitação de local de <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitação de local"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Pedido de localização"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitado por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Sim"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Não"</string>
@@ -1589,7 +1588,7 @@
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string>
<string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefone"</string>
- <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes da dock"</string>
+ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes na base"</string>
<string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string>
<string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5287600..df52f3b 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Efetue uma reposição de dados de fábrica para desativar o Modo de estrutura de teste."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Líquido ou resíduos na porta USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é automaticamente desativada. Toque para saber mais."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro utilizar a porta USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"O telemóvel já não deteta líquidos nem resíduos."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"A criar relatório de erro…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Pretende partilhar o relatório de erro?"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index fbabb34..e0047ff 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Realize uma redefinição para configuração original para desativar o modo Arcabouço de testes."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Líquido ou detrito na porta USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é desativada automaticamente. Toque para saber mais."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro usar a porta USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Não há mais líquidos ou detritos detectados no smartphone."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"Localizar próximo"</string>
<string name="find_previous" msgid="2196723669388360506">"Localizar anterior"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitação de local de <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitação de local"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Pedido de localização"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitado por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Sim"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Não"</string>
@@ -1589,7 +1588,7 @@
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string>
<string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefone"</string>
- <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes da dock"</string>
+ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes na base"</string>
<string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string>
<string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index bda936e..004fc6f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1379,8 +1379,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Reveniți la setările din fabrică pentru a dezactiva modul Set de testare."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Lichide sau reziduuri în portul USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Portul USB este dezactivat automat. Atingeți ca să aflați mai multe."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Portul USB poate fi folosit"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefonul nu mai detectează lichide sau reziduuri."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Se creează un raport de eroare…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Trimiteți raportul de eroare?"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index dc3a810..e0dcd7c 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Чтобы отключить тестовый режим, сбросьте настройки до заводских."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"В USB-порт попала вода или грязь"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-порт был автоматически отключен. Нажмите, чтобы узнать подробности."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB-порт можно использовать"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Вода или грязь внутри не обнаружена."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Подготовка отчета об ошибке"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Разрешить доступ к информации об ошибке?"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 222d648..e6784dd 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Ak chcete zakázať režim správcu testov, obnovte výrobné nastavenia."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Tekutina alebo nečistoty v porte USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Port USB je automaticky deaktivovaný. Ďalšie informácie zobrazíte klepnutím."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Port USB môžete použiť"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefón už nerozpoznáva tekutinu ani nečistoty."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Preberá sa hlásenie chyby…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chcete zdieľať hlásenie chyby?"</string>
@@ -1540,7 +1539,7 @@
<string name="find_next" msgid="5742124618942193978">"Nájsť ďalšiu"</string>
<string name="find_previous" msgid="2196723669388360506">"Nájsť predchádzajúcu"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Žiadosť o informácie o polohe od používateľa <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Žiadosť o informácie o polohe"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Žiadosť o informácie o polohe"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Žiadosť od používateľa <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Áno"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Nie"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c8e3a9d..9fa767c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Če želite onemogočiti način preizkusnega ogrodja, ponastavite napravo na tovarniške nastavitve."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"V vratih USB je tekočina ali umazanija"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Vrata USB so samodejno onemogočena. Dotaknite se, če želite izvedeti več."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Vrata USB so varna za uporabo"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon ne zaznava več tekočine ali umazanije."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zajemanje poročila o napakah …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite poslati poročilo o napakah?"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 72ee396..57136eb 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Kryej një rivendosje në cilësimet e fabrikës për të çaktivizuar \"Modalitetin e lidhjes së testimit\"."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Lëngje ose papastërti në portën e USB-së"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Porta e USB-së është çaktivizuar automatikisht. Trokit për të mësuar më shumë."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Në rregulloj për përdorimin e portës USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefoni nuk i dallon më lëngjet apo papastërtitë."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Po merret raporti i defekteve në kod…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Të ndahet raporti i defektit në kod?"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 96d97dd..1912715 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1379,8 +1379,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Обавите ресетовање на фабричка подешавања да бисте онемогућили режим пробног коришћења."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Течност или нечистоћа у USB порту"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB порт је аутоматски искључен. Додирните да бисте сазнали више."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Коришћење USB порта је дозвољено"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Телефон више не открива течност или нечистоћу."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Извештај о грешци се генерише…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Желите ли да поделите извештај о грешци?"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index a7f74c9..e93be4f 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Inaktivera testverktygsläget genom att göra en återställning till standardinställningarna."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Vätska eller smuts i USB-porten"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-porten har inaktiverats automatiskt. Tryck för att läsa mer."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Nu kan du använda USB-porten"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Mobilen känner inte längre av någon vätska eller smuts."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Felrapporten överförs …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"Sök nästa"</string>
<string name="find_previous" msgid="2196723669388360506">"Sök föregående"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Positionsförfrågan från <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Positionsförfrågan"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Platsförfrågan"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Begärt av <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Ja"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Nej"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index dec924e..99b64b1 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Rejesha mipangilio iliyotoka nayo kiwandani ili uzime hali ya Muunganisho wa Majaribio."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Unyevu au uchafu katika mlango wa USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Mlango wa USB umezimwa kiotomatiki. Gusa ili upate maelezo zaidi."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Ni sawa kutumia mlango wa USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Simu haitambui tena unyevu au uchafu."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Inatayarisha ripoti ya hitilafu…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Ungependa kushiriki ripoti ya hitilafu?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"Pata ifuatayo"</string>
<string name="find_previous" msgid="2196723669388360506">"Pata iliyotangulia"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Ombi la mahali kutoka <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Ombi la mahali"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Ombi la kutambua mahali"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Imeombwa na <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Ndiyo"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Hapana"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 97a8df2..8bfc80c 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"’தன்னியக்க சோதனைப்\' பயன்முறையை முடக்க ஆரம்பநிலைக்கு மீட்டமைக்கவும்."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB போர்ட்டில் சேதம் உள்ளது"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB போர்ட் தானாகவே முடக்கப்பட்டது மேலும் அறிய, தட்டவும்."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB போர்ட்டைப் பயன்படுத்தலாம்"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"மொபைலில் எந்தச் சேதாரமும் கண்டறியப்படவில்லை."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"பிழை அறிக்கையை எடுக்கிறது…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"பிழை அறிக்கையைப் பகிரவா?"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index a0da181..461af6e 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -280,7 +280,7 @@
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"మీ పరిచయాలను యాక్సెస్ చేయడానికి <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని అనుమతించాలా?"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"స్థానం"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి"</string>
- <string name="permgrouprequest_location" msgid="3788275734953323491">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని అనుమతించాలా?"</string>
+ <string name="permgrouprequest_location" msgid="3788275734953323491">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ను అనుమతించాలా?"</string>
<string name="permgrouprequestdetail_location" msgid="1347189607421252902">"మీరు యాప్ను ఉపయోగిస్తున్నప్పుడు మాత్రమే స్థానానికి యాప్ యాక్సెస్ కలిగి ఉంటుంది"</string>
<string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"ఈ పరికర స్థానాన్ని <b>అన్ని సమయాలలో</b> యాక్సెస్ చేయడానికి <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ను అనుమతించాలా?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"యాప్ ప్రస్తుతం మీరు ఆ యాప్ను ఉపయోగిస్తున్నప్పుడు మాత్రమే స్థానాన్ని యాక్సెస్ చేయగలుగుతుంది"</string>
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"పరీక్ష నియంత్రణ మోడ్ను నిలిపివేయడానికి ఫ్యాక్టరీ రీసెట్ను అమలు చేయండి."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB పోర్ట్లో ద్రవ లేదా వ్యర్థ పదార్థాలు ఉన్నాయి"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB పోర్ట్ ఆటోమేటిక్గా నిలిపివేయబడింది. మరింత తెలుసుకోవడానికి నొక్కండి."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB పోర్ట్ను ఉపయోగించడం సురక్షితం"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"ఫోన్ ఇకపై ద్రవ లేదా వ్యర్థ పదార్థాలను గుర్తించదు."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"బగ్ నివేదికను తీస్తోంది…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"బగ్ నివేదికను భాగస్వామ్యం చేయాలా?"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 2bf0a9c..9516522 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"รีเซ็ตเป็นค่าเริ่มต้นเพื่อปิดใช้โหมดโปรแกรมทดสอบอัตโนมัติ"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"มีของเหลวหรือฝุ่นละอองในพอร์ต USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"พอร์ต USB ปิดใช้โดยอัตโนมัติ แตะเพื่อดูข้อมูลเพิ่มเติม"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"ใช้พอร์ต USB ได้แล้ว"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"โทรศัพท์ไม่ได้ตรวจจับของเหลวและฝุ่นละอองแล้ว"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"กำลังสร้างรายงานข้อบกพร่อง…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"แชร์รายงานข้อบกพร่องไหม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 02410f2..d102c3c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Mag-factory reset para i-disable ang Test Harness Mode."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Liquid o debris sa USB port"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Awtomatikong na-disable ang USB port. Mag-tap para matuto pa."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Ayos na gamitin ang USB port"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Hindi na nakaka-detect ang telepono ng liquid o debris."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kinukuha ang ulat ng bug…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Gusto mo bang ibahagi ang ulat ng bug?"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 6800a72..bbfe7de 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Test Bandı Modu\'nu devre dışı bırakmak için cihazı fabrika ayarlarına sıfırlayın."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB bağlantı noktasında sıvı veya toz var"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB bağlantı noktası otomatik olarak devre dışı bırakıldı. Daha fazla bilgi için dokunun."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB bağlantı noktasını kullanabilirsiniz"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon artık sıvıları veya tozları algılamıyor."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hata raporu alınıyor…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Hata raporu paylaşılsın mı?"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 993223772..2354c6b 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1401,8 +1401,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Щоб вимкнути режим автоматизованого тестування, відновіть заводські налаштування."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Рідина або сміття в USB-порту"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB-порт автоматично вимкнено. Торкніться, щоб дізнатися більше."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Можна використовувати USB-порт"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Телефон уже не виявляє рідини або сміття."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Створюється повідомлення про помилку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Надіслати звіт про помилку?"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 3deaa84..45d0e86 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"ٹیسٹ ہارنیس موڈ غیر فعال کرنے کے لیے فیکٹری ری سیٹ کریں۔"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB پورٹ میں سیال یا دھول ہے"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB پورٹ خودکار طور پر غیر فعال کر دیا گیا۔ مزید جاننے کیلئے تھپتھپائیں۔"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB پورٹ کا استعمال ٹھیک ہے"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"فون مزید سیال یا دھول کا پتہ نہیں لگاتا۔"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"بگ رپورٹ لی جا رہی ہے…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"بگ رپورٹ کا اشتراک کریں؟"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 1edf644..271c8f9 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1358,8 +1358,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Xavfsizlik sinovi rejimini faolsizlantirish uchun zavod sozlamalariga qaytaring."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB portda suyuqlik yoki parcha bor"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB port avtomatik tarzda faolsizlashtirildi. Batafsil axborot olish uchun bosing."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB portdan foydalanish mumkin"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Telefon endi suyuqlik yoki turli parchalarni aniqlay olmaydi."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Xatoliklar hisoboti olinmoqda…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Xatoliklar hisoboti yuborilsinmi?"</string>
@@ -1495,7 +1494,7 @@
<string name="find_next" msgid="5742124618942193978">"Keyingisini topish"</string>
<string name="find_previous" msgid="2196723669388360506">"Oldingisini topish"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>dan manzil haqida so‘rov"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Manzil so‘rovi"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Joylashuv axboroti talabi"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) tomonidan so‘raldi"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Ha"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Yo‘q"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7c69ee4..eb147a1 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -683,7 +683,7 @@
<string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Ngăn sử dụng một số tính năng của phương thức khóa màn hình."</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Nhà riêng"</item>
- <item msgid="869923650527136615">"Di Động"</item>
+ <item msgid="869923650527136615">"Di động"</item>
<item msgid="7897544654242874543">"Cơ quan"</item>
<item msgid="1103601433382158155">"Số fax cơ quan"</item>
<item msgid="1735177144948329370">"Số fax nhà riêng"</item>
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Khôi phục cài đặt gốc để tắt Chế độ khai thác kiểm thử."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Có chất lỏng hoặc mảnh vỡ trong cổng USB"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"Cổng USB đã tự động tắt. Nhấn để tìm hiểu thêm."</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Có thể sử dụng cổng USB"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Điện thoại không còn phát hiện chất lỏng hay mảnh vỡ nữa."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Đang thu thập báo cáo lỗi…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chia sẻ báo cáo lỗi?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"Tìm kết quả phù hợp tiếp theo"</string>
<string name="find_previous" msgid="2196723669388360506">"Tìm kết quả phù hợp trước"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Yêu cầu vị trí từ <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Yêu cầu vị trí"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Yêu cầu truy cập vị trí"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Được yêu cầu bởi <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Có"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Không"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index eb8e9bb..7c458dc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"恢复出厂设置以停用自动化测试框架模式。"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB 端口中有液体或碎屑"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB 端口已自动停用。点按即可了解详情。"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"允许使用 USB 端口"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"手机不再检测到液体或碎屑。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在生成错误报告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享错误报告吗?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"下一条结果"</string>
<string name="find_previous" msgid="2196723669388360506">"上一条结果"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"来自<xliff:g id="NAME">%s</xliff:g>的定位请求"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"定位请求"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"位置信息请求"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"请求人:<xliff:g id="NAME">%1$s</xliff:g>(<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"是"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"否"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index e3def2e..29d62c2 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"請將裝置回復原廠設定,以停用測試工具模式。"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB 連接埠中有液體或碎片"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB 連接埠已自動停用。輕按即可瞭解詳情。"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"USB 連接埠可安全使用"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"手機不再偵測到液體或碎片。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在取得錯誤報告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9c1b05d..a2c84c2 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1357,8 +1357,7 @@
<string name="test_harness_mode_notification_message" msgid="1343197173054407119">"恢復原廠設定以停用測試控管工具模式。"</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"USB 連接埠中有液體或灰塵"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"系統已自動停用 USB 連接埠。輕觸即可瞭解詳情。"</string>
- <!-- no translation found for usb_contaminant_not_detected_title (7708281124088684821) -->
- <skip />
+ <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"現在可以使用 USB 連接埠"</string>
<string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"手機目前無法偵測液體或灰塵。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在接收錯誤報告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
@@ -1494,7 +1493,7 @@
<string name="find_next" msgid="5742124618942193978">"尋找下一個項目"</string>
<string name="find_previous" msgid="2196723669388360506">"尋找上一個項目"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> 的地點要求"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"位置要求"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"位置資訊要求"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"要求者:<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"是"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"否"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2beef42..9bd56ad 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3902,6 +3902,10 @@
{@see android.view.Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS} -->
<string name="config_secondaryHomeComponent" translatable="false">com.android.launcher3/com.android.launcher3.SecondaryDisplayLauncher</string>
+ <!-- Force secondary home launcher specified in config_secondaryHomeComponent always. If this is
+ not set, secondary home launcher can be replaced by user. -->
+ <bool name ="config_useSystemProvidedLauncherForSecondary">false</bool>
+
<!-- If device supports corner radius on windows.
This should be turned off on low-end devices to improve animation performance. -->
<bool name="config_supportsRoundedCornersOnWindows">true</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5b917cc..e3f84c0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -252,12 +252,15 @@
<item>@string/wfcSpnFormat_wifi</item>
<item>@string/wfcSpnFormat_wifi_calling_wo_hyphen</item>
<item>@string/wfcSpnFormat_vowifi</item>
+ <item>@string/wfcSpnFormat_spn_wifi_calling_vo_hyphen</item>
</string-array>
<!-- Spn during Wi-Fi Calling: "<operator>" -->
<string name="wfcSpnFormat_spn"><xliff:g id="spn" example="Operator">%s</xliff:g></string>
<!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi Calling" -->
<string name="wfcSpnFormat_spn_wifi_calling"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi Calling</string>
+ <!-- Spn during Wi-Fi Calling: "<operator> WiFi Calling" -->
+ <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen"><xliff:g id="spn" example="Operator">%s</xliff:g> WiFi Calling</string>
<!-- Spn during Wi-Fi Calling: "WLAN Call" -->
<string name="wfcSpnFormat_wlan_call">WLAN Call</string>
<!-- Spn during Wi-Fi Calling: "<operator> WLAN Call" -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4af05f6..3b3a062 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3699,6 +3699,7 @@
<!-- For Secondary Launcher -->
<java-symbol type="string" name="config_secondaryHomeComponent" />
+ <java-symbol type="bool" name="config_useSystemProvidedLauncherForSecondary" />
<java-symbol type="string" name="battery_saver_notification_channel_name" />
<java-symbol type="string" name="battery_saver_sticky_disabled_notification_title" />
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
index cc0ddb7..cd61011 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
@@ -22,25 +22,28 @@
import android.content.Context;
import android.os.Parcel;
+import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
/**
* Test BatteryStatsHistory.
*/
@RunWith(AndroidJUnit4.class)
public class BatteryStatsHistoryTest {
+ private static final String TAG = "BatteryStatsHistoryTest";
private static final int MAX_HISTORY_FILES = 32;
private final BatteryStatsImpl mBatteryStatsImpl = new MockBatteryStatsImpl();
private final Parcel mHistoryBuffer = Parcel.obtain();
@@ -53,6 +56,12 @@
Context context = InstrumentationRegistry.getContext();
mSystemDir = context.getDataDir();
mHistoryDir = new File(mSystemDir, BatteryStatsHistory.HISTORY_DIR);
+ String[] files = mHistoryDir.list();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ new File(mHistoryDir, files[i]).delete();
+ }
+ }
mHistoryDir.delete();
}
@@ -60,28 +69,32 @@
public void testConstruct() {
BatteryStatsHistory history =
new BatteryStatsHistory(mBatteryStatsImpl, mSystemDir, mHistoryBuffer);
+ createActiveFile(history);
verifyFileNumbers(history, Arrays.asList(0));
verifyActiveFile(history, "0.bin");
}
@Test
- public void testCreateNextFile() {
+ public void testStartNextFile() {
BatteryStatsHistory history =
new BatteryStatsHistory(mBatteryStatsImpl, mSystemDir, mHistoryBuffer);
List<Integer> fileList = new ArrayList<>();
fileList.add(0);
+ createActiveFile(history);
// create file 1 to 31.
for (int i = 1; i < MAX_HISTORY_FILES; i++) {
fileList.add(i);
- history.createNextFile();
+ history.startNextFile();
+ createActiveFile(history);
verifyFileNumbers(history, fileList);
verifyActiveFile(history, i + ".bin");
}
// create file 32
- history.createNextFile();
+ history.startNextFile();
+ createActiveFile(history);
fileList.add(32);
fileList.remove(0);
// verify file 0 is deleted.
@@ -90,7 +103,8 @@
verifyActiveFile(history, "32.bin");
// create file 33
- history.createNextFile();
+ history.startNextFile();
+ createActiveFile(history);
// verify file 1 is deleted
fileList.add(33);
fileList.remove(0);
@@ -108,6 +122,7 @@
verifyActiveFile(history2, "33.bin");
history2.resetAllFiles();
+ createActiveFile(history2);
// verify all existing files are deleted.
for (int i = 2; i < 33; ++i) {
verifyFileDeleted(i + ".bin");
@@ -118,7 +133,8 @@
verifyActiveFile(history2, "0.bin");
// create file 1.
- history2.createNextFile();
+ history2.startNextFile();
+ createActiveFile(history2);
verifyFileNumbers(history2, Arrays.asList(0, 1));
verifyActiveFile(history2, "1.bin");
}
@@ -142,4 +158,13 @@
private void verifyFileDeleted(String file) {
assertFalse(new File(mHistoryDir, file).exists());
}
+
+ private void createActiveFile(BatteryStatsHistory history) {
+ final File file = history.getActiveFile().getBaseFile();
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Error creating history file " + file.getPath(), e);
+ }
+ }
}
\ No newline at end of file
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 987db8b..fde0e64 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -990,9 +990,9 @@
public static native int setMasterBalance(float balance);
// helpers for android.media.AudioManager.getProperty(), see description there for meaning
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 112561552)
+ @UnsupportedAppUsage(trackingBug = 134049522)
public static native int getPrimaryOutputSamplingRate();
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 112561552)
+ @UnsupportedAppUsage(trackingBug = 134049522)
public static native int getPrimaryOutputFrameCount();
@UnsupportedAppUsage
public static native int getOutputLatency(int stream);
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 112ce1d..c43b78c 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -869,7 +869,7 @@
* This key retrieves the location information, if available.
* The location should be specified according to ISO-6709 standard, under
* a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude
- * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance.
+ * of 180 degrees will be retrieved as "+180.0000-90.0000/", for instance.
*/
public static final int METADATA_KEY_LOCATION = 23;
/**
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index 72914f7..dac5f2a 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -32,7 +32,7 @@
<color name="system_bar_background_opaque">#ff172026</color>
<color name="status_bar_background_color">#33000000</color>
- <drawable name="system_bar_background">@color/status_bar_background_color</drawable>
+ <drawable name="system_bar_background">@android:color/transparent</drawable>
<!-- The background color of the notification shade -->
<color name="notification_shade_background_color">#DD000000</color>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 7fbdc2e..8373761 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -1259,6 +1259,10 @@
@Override
protected void setHeadsUpVisible() {
+ // if the Notifications panel is showing don't show the Heads up
+ if (mPanelExpanded) {
+ return;
+ }
super.setHeadsUpVisible();
if (mHeadsUpPanel.getVisibility() == View.VISIBLE) {
mStatusBarWindowController.setHeadsUpShowing(true);
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
deleted file mode 100644
index b7b21fa..0000000
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#242424" /> <!-- 14% of white -->
- <padding android:paddingTop="@dimen/ongoing_appops_chip_bg_padding"
- android:paddingBottom="@dimen/ongoing_appops_chip_bg_padding" />
- <corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
deleted file mode 100644
index dce9ce1..0000000
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-
-<com.android.systemui.privacy.OngoingPrivacyChip
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/privacy_chip"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical|end"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:focusable="true" >
-
- <FrameLayout
- android:id="@+id/background"
- android:layout_height="@dimen/ongoing_appops_chip_height"
- android:minWidth="48dp"
- android:layout_width="wrap_content" >
- <LinearLayout
- android:id="@+id/icons_container"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:gravity="center_vertical"
- />
- </FrameLayout>
-</com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_text_item.xml b/packages/SystemUI/res/layout/ongoing_privacy_text_item.xml
deleted file mode 100644
index 5595b13..0000000
--- a/packages/SystemUI/res/layout/ongoing_privacy_text_item.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textDirection="locale"
- android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary"
-/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index c812489..683e867 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -21,6 +21,7 @@
android:layout_below="@id/quick_status_bar_system_icons"
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingEnd="@dimen/status_bar_padding_end"
+ android:visibility="invisible"
android:theme="@style/QSHeaderTheme">
<com.android.systemui.qs.QSHeaderInfoLayout
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index cd9f780..54fb216 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -22,19 +22,11 @@
android:layout_height="@*android:dimen/quick_qs_offset_height"
android:clipChildren="false"
android:clipToPadding="false"
- android:gravity="center"
android:orientation="horizontal"
android:clickable="true"
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingEnd="@dimen/status_bar_padding_end" >
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:gravity="center_vertical|start" >
-
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:layout_width="wrap_content"
@@ -46,23 +38,4 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
systemui:showDark="false" />
- </LinearLayout>
-
- <android.widget.Space
- android:id="@+id/space"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center_vertical|center_horizontal"
- android:visibility="gone" />
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:gravity="center_vertical|end" >
-
- <include layout="@layout/ongoing_privacy_chip" />
-
- </LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index c5f4052..7b55d18 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -46,7 +46,7 @@
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
<color name="notification_guts_link_icon_tint">@color/GM2_grey_500</color>
- <color name="notification_guts_sub_text_color">@color/GM2_grey_500</color>
+ <color name="notification_guts_sub_text_color">@color/GM2_grey_300</color>
<color name="notification_guts_header_text_color">@color/GM2_grey_200</color>
<color name="notification_guts_info_button_color">@color/GM2_blue_300</color>
<color name="notification_guts_priority_button_content_color">@color/GM2_grey_500</color>
@@ -54,7 +54,7 @@
<color name="notification_guts_priority_button_bg_fill_color">@color/transparent</color>
<color name="notification_guts_priority_button_bg_fill_color_selected">@color/GM2_grey_800</color>
<color name="notification_guts_priority_button_bg_stroke_color">@color/GM2_grey_700</color>
- <color name="notification_guts_priority_button_bg_stroke_color_selected">@color/GM2_grey_700</color>
+ <color name="notification_guts_priority_button_bg_stroke_color_selected">@color/GM2_blue_300</color>
<color name="notification_section_header_label_color">@color/GM2_grey_200</color>
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8174434..3fe2492 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -495,6 +495,9 @@
<!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
+ <!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$s</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
+
<!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 2090748..c26fdc2 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -324,13 +324,25 @@
final CharSequence[] carrierNames = new CharSequence[numSubs];
if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs);
+ boolean anySimEmergency = mKeyguardUpdateMonitor.isAnySimEmergencyAble();
for (int i = 0; i < numSubs; i++) {
int subId = subs.get(i).getSubscriptionId();
carrierNames[i] = "";
subsIds[i] = subId;
subOrderBySlot[subs.get(i).getSimSlotIndex()] = i;
IccCardConstants.State simState = mKeyguardUpdateMonitor.getSimState(subId);
+ ServiceState s = mKeyguardUpdateMonitor.getServiceState(subId);
CharSequence carrierName = subs.get(i).getCarrierName();
+ // If this sub is showing No service but at least one slot currently supports emergency
+ // calls, it should replace it by Emergency calls only
+ if (s != null && s.getState() != ServiceState.STATE_IN_SERVICE && !s.isEmergencyOnly()
+ && anySimEmergency) {
+ carrierName = getContext().getText(
+ com.android.internal.R.string.emergency_calls_only);
+ if (DEBUG) {
+ Log.d(TAG, "Subscription " + subId + "switched to ECO");
+ }
+ }
CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
if (DEBUG) {
Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName);
@@ -340,16 +352,15 @@
carrierNames[i] = carrierTextForSimState;
}
if (simState == IccCardConstants.State.READY) {
- ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
- if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
+ if (s != null && s.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
// hack for WFC (IWLAN) not turning off immediately once
// Wi-Fi is disassociated or disabled
- if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
+ if (s.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
|| (mWifiManager.isWifiEnabled()
&& mWifiManager.getConnectionInfo() != null
&& mWifiManager.getConnectionInfo().getBSSID() != null)) {
if (DEBUG) {
- Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss);
+ Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + s);
}
anySimReadyAndInService = true;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6a4dbc8d..446366b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -195,6 +195,12 @@
HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>();
+ /**
+ * Support up to 3 slots which is what's supported by {@link TelephonyManager#getPhoneCount}
+ */
+ private static final int SIM_SLOTS = 3;
+ private final ServiceState[] mServiceStatesBySlot = new ServiceState[SIM_SLOTS];
+
private int mRingMode;
private int mPhoneState;
private boolean mKeyguardIsVisible;
@@ -326,7 +332,7 @@
handleAirplaneModeChanged();
break;
case MSG_SERVICE_STATE_CHANGE:
- handleServiceStateChange(msg.arg1, (ServiceState) msg.obj);
+ handleServiceStateChange(msg.arg1, msg.arg2, (ServiceState) msg.obj);
break;
case MSG_SCREEN_TURNED_ON:
handleScreenTurnedOn();
@@ -1038,12 +1044,13 @@
ServiceState serviceState = ServiceState.newFromBundle(intent.getExtras());
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, -1);
if (DEBUG) {
Log.v(TAG, "action " + action + " serviceState=" + serviceState + " subId="
+ subId);
}
- mHandler.sendMessage(
- mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
+ mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, slotId, serviceState)
+ .sendToTarget();
} else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
action)) {
mHandler.sendEmptyMessage(MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -2042,6 +2049,14 @@
*/
@VisibleForTesting
void handleServiceStateChange(int subId, ServiceState serviceState) {
+ handleServiceStateChange(subId, -1, serviceState);
+ }
+
+ /**
+ * Handle {@link #MSG_SERVICE_STATE_CHANGE}
+ */
+ @VisibleForTesting
+ void handleServiceStateChange(int subId, int slotId, ServiceState serviceState) {
if (DEBUG) {
Log.d(TAG,
"handleServiceStateChange(subId=" + subId + ", serviceState=" + serviceState);
@@ -2055,6 +2070,7 @@
}
mServiceStates.put(subId, serviceState);
+ if (slotId >= 0 && slotId < SIM_SLOTS) mServiceStatesBySlot[slotId] = serviceState;
for (int j = 0; j < mCallbacks.size(); j++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
@@ -2280,6 +2296,21 @@
return mServiceStates.get(subId);
}
+ /**
+ * @return true iff at least one slot currently supports emergency calls
+ */
+ public boolean isAnySimEmergencyAble() {
+ for (int i = 0; i < SIM_SLOTS; i++) {
+ ServiceState s = mServiceStatesBySlot[i];
+ if (s != null) {
+ if (s.getState() == ServiceState.STATE_IN_SERVICE || s.isEmergencyOnly()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public void clearBiometricRecognized() {
mUserFingerprintAuthenticated.clear();
mUserFaceAuthenticated.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index bce5c23..f66463e 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -356,8 +356,8 @@
if (estimate != null) {
mBatteryPercentView.setText(estimate);
setContentDescription(getContext().getString(
- R.string.battery_low_percent_format_hybrid, mLevel, estimate));
-
+ R.string.accessibility_battery_level_with_estimate,
+ mLevel, estimate));
} else {
setPercentTextAtCurrentLevel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index 528db5a..691c3f9 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -36,9 +36,9 @@
public class CornerHandleView extends View {
private static final boolean ALLOW_TUNING = false;
private static final int ANGLE_DEGREES = 50;
- public static final int MARGIN_DP = 11;
- public static final int RADIUS_DP = 37;
- public static final float STROKE_DP = 2.5f;
+ private static final float STROKE_DP = 2.5f;
+ // Radius to use if none is available.
+ private static final int FALLBACK_RADIUS_DP = 15;
private Paint mPaint;
private int mLightColor;
@@ -71,7 +71,7 @@
/**
* Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
- * approriately. Intention is to match the home handle color.
+ * appropriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
@@ -115,20 +115,37 @@
}
private int getMarginPx() {
+ // Hand-derived function to map radiusPx to the margin amount.
+ // https://www.wolframalpha.com/input/?i=0.001402+*+x+%5E2%E2%88%920.08661+*+x%2B17.20+from+40+to+180
+ int radius = getRadiusPx();
+ int marginPx = (int) (0.001402f * radius * radius - 0.08661f * radius + 17.2f);
if (ALLOW_TUNING) {
- return SystemProperties.getInt("CORNER_HANDLE_MARGIN_PX",
- (int) convertDpToPixel(MARGIN_DP, getContext()));
+ return SystemProperties.getInt("CORNER_HANDLE_MARGIN_PX", marginPx);
} else {
- return (int) convertDpToPixel(MARGIN_DP, getContext());
+ return marginPx;
}
}
private int getRadiusPx() {
+ // Attempt to get the bottom corner radius, otherwise fall back on the generic or top
+ // values. If none are available, use the FALLBACK_RADIUS_DP.
+ int radius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.rounded_corner_radius_bottom);
+ if (radius == 0) {
+ radius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.rounded_corner_radius);
+ }
+ if (radius == 0) {
+ radius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.rounded_corner_radius_top);
+ }
+ if (radius == 0) {
+ radius = (int) convertDpToPixel(FALLBACK_RADIUS_DP, mContext);
+ }
if (ALLOW_TUNING) {
- return SystemProperties.getInt("CORNER_HANDLE_RADIUS_PX",
- (int) convertDpToPixel(RADIUS_DP, getContext()));
+ return SystemProperties.getInt("CORNER_HANDLE_RADIUS_PX", radius);
} else {
- return (int) convertDpToPixel(RADIUS_DP, getContext());
+ return radius;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 7a82402..9f4a4e0 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -48,7 +48,6 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.PowerUI;
-import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -287,7 +286,6 @@
@Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
@Inject Lazy<AutoHideController> mAutoHideController;
@Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener;
- @Inject Lazy<PrivacyItemController> mPrivacyItemController;
@Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper;
@Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler;
@Inject @Named(MAIN_HANDLER_NAME) Lazy<Handler> mMainHandler;
@@ -472,7 +470,6 @@
mProviders.put(ForegroundServiceNotificationListener.class,
mForegroundServiceNotificationListener::get);
mProviders.put(ClockManager.class, mClockManager::get);
- mProviders.put(PrivacyItemController.class, mPrivacyItemController::get);
mProviders.put(ActivityManagerWrapper.class, mActivityManagerWrapper::get);
mProviders.put(DevicePolicyManagerWrapper.class, mDevicePolicyManagerWrapper::get);
mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get);
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 49bd5bd..afb8e74 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -20,7 +20,6 @@
import android.app.AppOpsManager;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -211,59 +210,6 @@
}
/**
- * Does the app-op code refer to a user sensitive permission for the specified user id
- * and package. Only user sensitive permission should be shown to the user by default.
- *
- * @param appOpCode The code of the app-op.
- * @param uid The uid of the user.
- * @param packageName The name of the package.
- *
- * @return {@code true} iff the app-op item is user sensitive
- */
- private boolean isUserSensitive(int appOpCode, int uid, String packageName) {
- String permission = AppOpsManager.opToPermission(appOpCode);
- if (permission == null) {
- return false;
- }
- int permFlags = mContext.getPackageManager().getPermissionFlags(permission,
- packageName, UserHandle.getUserHandleForUid(uid));
- return (permFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0;
- }
-
- /**
- * Does the app-op item refer to an operation that should be shown to the user.
- * Only specficic ops (like SYSTEM_ALERT_WINDOW) or ops that refer to user sensitive
- * permission should be shown to the user by default.
- *
- * @param item The item
- *
- * @return {@code true} iff the app-op item should be shown to the user
- */
- private boolean isUserVisible(AppOpItem item) {
- return isUserVisible(item.getCode(), item.getUid(), item.getPackageName());
- }
-
-
- /**
- * Does the app-op, uid and package name, refer to an operation that should be shown to the
- * user. Only specficic ops (like {@link AppOpsManager.OP_SYSTEM_ALERT_WINDOW}) or
- * ops that refer to user sensitive permission should be shown to the user by default.
- *
- * @param item The item
- *
- * @return {@code true} iff the app-op for should be shown to the user
- */
- private boolean isUserVisible(int appOpCode, int uid, String packageName) {
- // currently OP_SYSTEM_ALERT_WINDOW does not correspond to a platform permission
- // which may be user senstive, so for now always show it to the user.
- if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW) {
- return true;
- }
-
- return isUserSensitive(appOpCode, uid, packageName);
- }
-
- /**
* Returns a copy of the list containing all the active AppOps that the controller tracks.
*
* @return List of active AppOps information
@@ -286,8 +232,8 @@
final int numActiveItems = mActiveItems.size();
for (int i = 0; i < numActiveItems; i++) {
AppOpItem item = mActiveItems.get(i);
- if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId)
- && isUserVisible(item)) {
+ if ((userId == UserHandle.USER_ALL
+ || UserHandle.getUserId(item.getUid()) == userId)) {
list.add(item);
}
}
@@ -296,8 +242,8 @@
final int numNotedItems = mNotedItems.size();
for (int i = 0; i < numNotedItems; i++) {
AppOpItem item = mNotedItems.get(i);
- if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId)
- && isUserVisible(item)) {
+ if ((userId == UserHandle.USER_ALL
+ || UserHandle.getUserId(item.getUid()) == userId)) {
list.add(item);
}
}
@@ -323,8 +269,7 @@
}
private void notifySuscribers(int code, int uid, String packageName, boolean active) {
- if (mCallbacksByCode.containsKey(code)
- && isUserVisible(code, uid, packageName)) {
+ if (mCallbacksByCode.containsKey(code)) {
for (Callback cb: mCallbacksByCode.get(code)) {
cb.onActiveStateChanged(code, uid, packageName, active);
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 01deb03..6d109fb 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -142,6 +142,10 @@
mHandler.post(() -> maybeShowHandles(/* ignoreThreshold = */ true));
}
+ boolean areHandlesShowing() {
+ return mHandlesShowing;
+ }
+
void onAssistantGesturePerformed() {
mBehaviorMap.get(mCurrentBehavior).onAssistantGesturePerformed();
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 2fc79d6..67fcd68 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -104,6 +104,11 @@
public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
+ public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
+ public static final int DISMISS_REASON_TAP = 2;
+ public static final int DISMISS_REASON_BACK = 3;
+ public static final int DISMISS_REASON_TIMEOUT = 4;
+
private static final long TIMEOUT_SERVICE = 2500;
private static final long TIMEOUT_ACTIVITY = 1000;
@@ -251,13 +256,14 @@
if (invocationType == INVOCATION_TYPE_GESTURE) {
mHandleController.onAssistantGesturePerformed();
}
- args.putInt(INVOCATION_PHONE_STATE_KEY, mPhoneStateMonitor.getPhoneState());
+ int phoneState = mPhoneStateMonitor.getPhoneState();
+ args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState);
args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.uptimeMillis());
// Logs assistant start with invocation type.
MetricsLogger.action(
new LogMaker(MetricsEvent.ASSISTANT)
- .setType(MetricsEvent.TYPE_OPEN).setSubtype(
- invocationType));
+ .setType(MetricsEvent.TYPE_OPEN)
+ .setSubtype(toLoggingSubType(invocationType, phoneState)));
startAssistInternal(args, assistComponent, isService);
}
@@ -437,4 +443,19 @@
public void onLockscreenShown() {
mAssistUtils.onLockscreenShown();
}
+
+ /** Returns the logging flags for the given Assistant invocation type. */
+ public int toLoggingSubType(int invocationType) {
+ return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
+ }
+
+ private int toLoggingSubType(int invocationType, int phoneState) {
+ // Note that this logic will break if the number of Assistant invocation types exceeds 7.
+ // There are currently 5 invocation types, but we will be migrating to the new logging
+ // framework in the next update.
+ int subType = mHandleController.areHandlesShowing() ? 0 : 1;
+ subType |= invocationType << 1;
+ subType |= phoneState << 4;
+ return subType;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index b1be811..95c136f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -16,6 +16,8 @@
package com.android.systemui.assist.ui;
+import static com.android.systemui.assist.AssistManager.DISMISS_REASON_INVOCATION_CANCELLED;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -91,6 +93,8 @@
@Override // AssistManager.UiController
public void onInvocationProgress(int type, float progress) {
+ boolean invocationWasInProgress = mInvocationInProgress;
+
if (progress == 1) {
animateInvocationCompletion(type, 0);
} else if (progress == 0) {
@@ -105,16 +109,7 @@
}
mLastInvocationProgress = progress;
- // Logs assistant invocation start.
- if (!mInvocationInProgress && progress > 0.f) {
- MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
- .setType(MetricsEvent.TYPE_ACTION));
- }
- // Logs assistant invocation cancelled.
- if (mInvocationInProgress && progress == 0f) {
- MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
- .setType(MetricsEvent.TYPE_DISMISS).setSubtype(0));
- }
+ logInvocationProgressMetrics(type, progress, invocationWasInProgress);
}
@Override // AssistManager.UiController
@@ -142,6 +137,22 @@
mInvocationLightsView.setColors(color1, color2, color3, color4);
}
+ protected static void logInvocationProgressMetrics(
+ int type, float progress, boolean invocationWasInProgress) {
+ // Logs assistant invocation start.
+ if (!invocationWasInProgress && progress > 0.f) {
+ MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
+ .setType(MetricsEvent.TYPE_ACTION)
+ .setSubtype(Dependency.get(AssistManager.class).toLoggingSubType(type)));
+ }
+ // Logs assistant invocation cancelled.
+ if (invocationWasInProgress && progress == 0f) {
+ MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
+ .setType(MetricsEvent.TYPE_DISMISS)
+ .setSubtype(DISMISS_REASON_INVOCATION_CANCELLED));
+ }
+ }
+
private void updateAssistHandleVisibility() {
ScreenDecorations decorations = SysUiServiceProvider.getComponent(mRoot.getContext(),
ScreenDecorations.class);
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 05665b5..835ffc9 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -16,6 +16,7 @@
package com.android.systemui.colorextraction;
+import android.annotation.ColorInt;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
@@ -113,7 +114,11 @@
super.onColorsChanged(colors, which);
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+ @ColorInt int oldColor = mWpHiddenColors.getMainColor();
updateDefaultGradients(colors);
+ if (oldColor != mWpHiddenColors.getMainColor()) {
+ triggerColorsChanged(WallpaperManager.FLAG_SYSTEM);
+ }
}
}
@@ -121,6 +126,7 @@
public void onUiModeChanged() {
WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
updateDefaultGradients(systemColors);
+ triggerColorsChanged(WallpaperManager.FLAG_SYSTEM);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
deleted file mode 100644
index a5a915b..0000000
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ /dev/null
@@ -1,110 +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.privacy
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.Gravity
-import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.ImageView
-import android.widget.LinearLayout
-import com.android.systemui.R
-
-class OngoingPrivacyChip @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttrs: Int = 0,
- defStyleRes: Int = 0
-) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
-
- private val iconMarginExpanded = context.resources.getDimensionPixelSize(
- R.dimen.ongoing_appops_chip_icon_margin_expanded)
- private val iconMarginCollapsed = context.resources.getDimensionPixelSize(
- R.dimen.ongoing_appops_chip_icon_margin_collapsed)
- private val iconSize =
- context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
- private val iconColor = context.resources.getColor(
- R.color.status_bar_clock_color, context.theme)
- private val sidePadding =
- context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
- private val backgroundDrawable = context.getDrawable(R.drawable.privacy_chip_bg)
- private lateinit var iconsContainer: LinearLayout
- private lateinit var back: FrameLayout
- var expanded = false
- set(value) {
- if (value != field) {
- field = value
- updateView()
- }
- }
-
- var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>())
- var privacyList = emptyList<PrivacyItem>()
- set(value) {
- field = value
- builder = PrivacyDialogBuilder(context, value)
- updateView()
- }
-
- override fun onFinishInflate() {
- super.onFinishInflate()
-
- back = findViewById(R.id.background)
- iconsContainer = findViewById(R.id.icons_container)
- }
-
- // Should only be called if the builder icons or app changed
- private fun updateView() {
- back.background = if (expanded) backgroundDrawable else null
- val padding = if (expanded) sidePadding else 0
- back.setPaddingRelative(padding, 0, padding, 0)
- fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
- iconsContainer.removeAllViews()
- dialogBuilder.generateIcons().forEachIndexed { i, it ->
- it.mutate()
- it.setTint(iconColor)
- val image = ImageView(context).apply {
- setImageDrawable(it)
- scaleType = ImageView.ScaleType.CENTER_INSIDE
- }
- iconsContainer.addView(image, iconSize, iconSize)
- if (i != 0) {
- val lp = image.layoutParams as MarginLayoutParams
- lp.marginStart = if (expanded) iconMarginExpanded else iconMarginCollapsed
- image.layoutParams = lp
- }
- }
- }
-
- if (!privacyList.isEmpty()) {
- generateContentDescription()
- setIcons(builder, iconsContainer)
- val lp = iconsContainer.layoutParams as FrameLayout.LayoutParams
- lp.gravity = Gravity.CENTER_VERTICAL or
- (if (expanded) Gravity.CENTER_HORIZONTAL else Gravity.END)
- iconsContainer.layoutParams = lp
- } else {
- iconsContainer.removeAllViews()
- }
- requestLayout()
- }
-
- private fun generateContentDescription() {
- val typesText = builder.joinTypes()
- contentDescription = context.getString(
- R.string.ongoing_privacy_chip_content_multiple_apps, typesText)
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
deleted file mode 100644
index d08a373..0000000
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ /dev/null
@@ -1,56 +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.privacy
-
-import android.content.Context
-import android.graphics.drawable.Drawable
-import com.android.systemui.R
-
-class PrivacyDialogBuilder(private val context: Context, itemsList: List<PrivacyItem>) {
-
- val appsAndTypes: List<Pair<PrivacyApplication, List<PrivacyType>>>
- val types: List<PrivacyType>
- private val separator = context.getString(R.string.ongoing_privacy_dialog_separator)
- private val lastSeparator = context.getString(R.string.ongoing_privacy_dialog_last_separator)
-
- init {
- appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
- .toList()
- .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
- { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
- types = itemsList.map { it.privacyType }.distinct().sorted()
- }
-
- fun generateIconsForApp(types: List<PrivacyType>): List<Drawable> {
- return types.sorted().map { it.getIcon(context) }
- }
-
- fun generateIcons() = types.map { it.getIcon(context) }
-
- private fun <T> List<T>.joinWithAnd(): StringBuilder {
- return subList(0, size - 1).joinTo(StringBuilder(), separator = separator).apply {
- append(lastSeparator)
- append(this@joinWithAnd.last())
- }
- }
-
- fun joinTypes(): String {
- return when (types.size) {
- 0 -> ""
- 1 -> types[0].getName(context)
- else -> types.map { it.getName(context) }.joinWithAnd().toString()
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
deleted file mode 100644
index 2909424..0000000
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ /dev/null
@@ -1,80 +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.privacy
-
-import android.content.Context
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import android.util.IconDrawableFactory
-import com.android.systemui.R
-
-typealias Privacy = PrivacyType
-
-enum class PrivacyType(private val nameId: Int, val iconId: Int) {
- // This is uses the icons used by the corresponding permission groups in the AndroidManifest
- TYPE_CAMERA(R.string.privacy_type_camera,
- com.android.internal.R.drawable.perm_group_camera),
- TYPE_MICROPHONE(R.string.privacy_type_microphone,
- com.android.internal.R.drawable.perm_group_microphone),
- TYPE_LOCATION(R.string.privacy_type_location,
- com.android.internal.R.drawable.perm_group_location);
-
- fun getName(context: Context) = context.resources.getString(nameId)
-
- fun getIcon(context: Context) = context.resources.getDrawable(iconId, context.theme)
-}
-
-data class PrivacyItem(
- val privacyType: PrivacyType,
- val application: PrivacyApplication
-)
-
-data class PrivacyApplication(val packageName: String, val uid: Int, val context: Context)
- : Comparable<PrivacyApplication> {
-
- override fun compareTo(other: PrivacyApplication): Int {
- return applicationName.compareTo(other.applicationName)
- }
-
- private val applicationInfo: ApplicationInfo? by lazy {
- try {
- val userHandle = UserHandle.getUserHandleForUid(uid)
- context.createPackageContextAsUser(packageName, 0, userHandle).getPackageManager()
- .getApplicationInfo(packageName, 0)
- } catch (_: PackageManager.NameNotFoundException) {
- null
- }
- }
- val icon: Drawable by lazy {
- applicationInfo?.let {
- try {
- val iconFactory = IconDrawableFactory.newInstance(context, true)
- iconFactory.getBadgedIcon(it, UserHandle.getUserId(uid))
- } catch (_: Exception) {
- null
- }
- } ?: context.getDrawable(android.R.drawable.sym_def_app_icon)
- }
-
- val applicationName: String by lazy {
- applicationInfo?.let {
- context.packageManager.getApplicationLabel(it) as String
- } ?: packageName
- }
-
- override fun toString() = "PrivacyApplication(packageName=$packageName, uid=$uid)"
-}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
deleted file mode 100644
index 82a2c1f..0000000
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ /dev/null
@@ -1,294 +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.privacy
-
-import android.app.ActivityManager
-import android.app.AppOpsManager
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import android.os.Handler
-import android.os.Looper
-import android.os.Message
-import android.os.UserHandle
-import android.os.UserManager
-import android.provider.DeviceConfig
-import com.android.internal.annotations.VisibleForTesting
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-import com.android.systemui.Dependency.BG_HANDLER_NAME
-import com.android.systemui.Dependency.MAIN_HANDLER_NAME
-import com.android.systemui.R
-import com.android.systemui.appops.AppOpItem
-import com.android.systemui.appops.AppOpsController
-import com.android.systemui.Dumpable
-import java.io.FileDescriptor
-import java.io.PrintWriter
-import java.lang.ref.WeakReference
-import javax.inject.Inject
-import javax.inject.Named
-import javax.inject.Singleton
-
-fun isPermissionsHubEnabled() = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false)
-
-@Singleton
-class PrivacyItemController @Inject constructor(
- val context: Context,
- private val appOpsController: AppOpsController,
- @Named(MAIN_HANDLER_NAME) private val uiHandler: Handler,
- @Named(BG_HANDLER_NAME) private val bgHandler: Handler
-) : Dumpable {
-
- @VisibleForTesting
- internal companion object {
- val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
- AppOpsManager.OP_RECORD_AUDIO,
- AppOpsManager.OP_COARSE_LOCATION,
- AppOpsManager.OP_FINE_LOCATION)
- val intents = listOf(Intent.ACTION_USER_FOREGROUND,
- Intent.ACTION_MANAGED_PROFILE_ADDED,
- Intent.ACTION_MANAGED_PROFILE_REMOVED)
- const val TAG = "PrivacyItemController"
- const val SYSTEM_UID = 1000
- const val MSG_ADD_CALLBACK = 0
- const val MSG_REMOVE_CALLBACK = 1
- const val MSG_UPDATE_LISTENING_STATE = 2
- }
-
- @VisibleForTesting
- internal var privacyList = emptyList<PrivacyItem>()
- @Synchronized get() = field.toList() // Returns a shallow copy of the list
- @Synchronized set
-
- private val userManager = context.getSystemService(UserManager::class.java)
- private var currentUserIds = emptyList<Int>()
- private var listening = false
- val systemApp =
- PrivacyApplication(context.getString(R.string.device_services), SYSTEM_UID, context)
- private val callbacks = mutableListOf<WeakReference<Callback>>()
- private val messageHandler = H(WeakReference(this), uiHandler.looper)
-
- private val notifyChanges = Runnable {
- val list = privacyList
- callbacks.forEach { it.get()?.privacyChanged(list) }
- }
-
- private val updateListAndNotifyChanges = Runnable {
- updatePrivacyList()
- uiHandler.post(notifyChanges)
- }
-
- private var indicatorsAvailable = isPermissionsHubEnabled()
- @VisibleForTesting
- internal val devicePropertyChangedListener =
- object : DeviceConfig.OnPropertyChangedListener {
- override fun onPropertyChanged(namespace: String, name: String, value: String?) {
- if (DeviceConfig.NAMESPACE_PRIVACY.equals(namespace) &&
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED.equals(name)) {
- indicatorsAvailable = java.lang.Boolean.parseBoolean(value)
- messageHandler.removeMessages(MSG_UPDATE_LISTENING_STATE)
- messageHandler.sendEmptyMessage(MSG_UPDATE_LISTENING_STATE)
- }
- }
- }
-
- private val cb = object : AppOpsController.Callback {
- override fun onActiveStateChanged(
- code: Int,
- uid: Int,
- packageName: String,
- active: Boolean
- ) {
- val userId = UserHandle.getUserId(uid)
- if (userId in currentUserIds) {
- update(false)
- }
- }
- }
-
- @VisibleForTesting
- internal var userSwitcherReceiver = Receiver()
- set(value) {
- context.unregisterReceiver(field)
- field = value
- registerReceiver()
- }
-
- init {
- DeviceConfig.addOnPropertyChangedListener(
- DeviceConfig.NAMESPACE_PRIVACY, context.mainExecutor, devicePropertyChangedListener)
- }
-
- private fun unregisterReceiver() {
- context.unregisterReceiver(userSwitcherReceiver)
- }
-
- private fun registerReceiver() {
- context.registerReceiverAsUser(userSwitcherReceiver, UserHandle.ALL, IntentFilter().apply {
- intents.forEach {
- addAction(it)
- }
- }, null, null)
- }
-
- private fun update(updateUsers: Boolean) {
- if (updateUsers) {
- val currentUser = ActivityManager.getCurrentUser()
- currentUserIds = userManager.getProfiles(currentUser).map { it.id }
- }
- bgHandler.post(updateListAndNotifyChanges)
- }
-
- /**
- * Updates listening status based on whether there are callbacks and the indicators are enabled
- *
- * This is only called from private (add/remove)Callback and from the config listener, all in
- * main thread.
- */
- private fun setListeningState() {
- val listen = !callbacks.isEmpty() and indicatorsAvailable
- if (listening == listen) return
- listening = listen
- if (listening) {
- appOpsController.addCallback(OPS, cb)
- registerReceiver()
- update(true)
- } else {
- appOpsController.removeCallback(OPS, cb)
- unregisterReceiver()
- // Make sure that we remove all indicators and notify listeners if we are not
- // listening anymore due to indicators being disabled
- update(false)
- }
- }
-
- private fun addCallback(callback: WeakReference<Callback>) {
- callbacks.add(callback)
- if (callbacks.isNotEmpty() && !listening) {
- messageHandler.removeMessages(MSG_UPDATE_LISTENING_STATE)
- messageHandler.sendEmptyMessage(MSG_UPDATE_LISTENING_STATE)
- }
- // Notify this callback if we didn't set to listening
- else if (listening) uiHandler.post(NotifyChangesToCallback(callback.get(), privacyList))
- }
-
- private fun removeCallback(callback: WeakReference<Callback>) {
- // Removes also if the callback is null
- callbacks.removeIf { it.get()?.equals(callback.get()) ?: true }
- if (callbacks.isEmpty()) {
- messageHandler.removeMessages(MSG_UPDATE_LISTENING_STATE)
- messageHandler.sendEmptyMessage(MSG_UPDATE_LISTENING_STATE)
- }
- }
-
- fun addCallback(callback: Callback) {
- messageHandler.obtainMessage(MSG_ADD_CALLBACK, callback).sendToTarget()
- }
-
- fun removeCallback(callback: Callback) {
- messageHandler.obtainMessage(MSG_REMOVE_CALLBACK, callback).sendToTarget()
- }
-
- private fun updatePrivacyList() {
- if (!listening) {
- privacyList = emptyList()
- return
- }
- val list = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
- .mapNotNull { toPrivacyItem(it) }.distinct()
- privacyList = list
- }
-
- private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
- val type: PrivacyType = when (appOpItem.code) {
- AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
- AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
- AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
- AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
- else -> return null
- }
- if (appOpItem.uid == SYSTEM_UID) return PrivacyItem(type, systemApp)
- val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid, context)
- return PrivacyItem(type, app)
- }
-
- // Used by containing class to get notified of changes
- interface Callback {
- fun privacyChanged(privacyItems: List<PrivacyItem>)
- }
-
- internal inner class Receiver : BroadcastReceiver() {
- override fun onReceive(context: Context?, intent: Intent?) {
- if (intent?.action in intents) {
- update(true)
- }
- }
- }
-
- private class NotifyChangesToCallback(
- private val callback: Callback?,
- private val list: List<PrivacyItem>
- ) : Runnable {
- override fun run() {
- callback?.privacyChanged(list)
- }
- }
-
- override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
- pw?.println("PrivacyItemController state:")
- pw?.println(" Listening: $listening")
- pw?.println(" Current user ids: $currentUserIds")
- pw?.println(" Privacy Items:")
- privacyList.forEach {
- pw?.print(" ")
- pw?.println(it.toString())
- }
- pw?.println(" Callbacks:")
- callbacks.forEach {
- it.get()?.let {
- pw?.print(" ")
- pw?.println(it.toString())
- }
- }
- }
-
- private class H(
- private val outerClass: WeakReference<PrivacyItemController>,
- looper: Looper
- ) : Handler(looper) {
- override fun handleMessage(msg: Message) {
- super.handleMessage(msg)
- when (msg.what) {
- MSG_UPDATE_LISTENING_STATE -> outerClass.get()?.setListeningState()
-
- MSG_ADD_CALLBACK -> {
- if (msg.obj !is PrivacyItemController.Callback) return
- outerClass.get()?.addCallback(
- WeakReference(msg.obj as PrivacyItemController.Callback))
- }
-
- MSG_REMOVE_CALLBACK -> {
- if (msg.obj !is PrivacyItemController.Callback) return
- outerClass.get()?.removeCallback(
- WeakReference(msg.obj as PrivacyItemController.Callback))
- }
- else -> {}
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 9842748..d59e251 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -32,30 +32,24 @@
import android.graphics.Rect;
import android.media.AudioManager;
import android.os.Handler;
-import android.os.Looper;
import android.provider.AlarmClock;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
-import android.util.StatsLog;
import android.view.ContextThemeWrapper;
import android.view.DisplayCutout;
import android.view.View;
import android.view.WindowInsets;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.RelativeLayout;
-import android.widget.Space;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DualToneHandler;
@@ -63,11 +57,6 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.privacy.OngoingPrivacyChip;
-import com.android.systemui.privacy.PrivacyDialogBuilder;
-import com.android.systemui.privacy.PrivacyItem;
-import com.android.systemui.privacy.PrivacyItemController;
-import com.android.systemui.privacy.PrivacyItemControllerKt;
import com.android.systemui.qs.QSDetail.Callback;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -78,8 +67,6 @@
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -121,7 +108,6 @@
private TintedIconManager mIconManager;
private TouchAnimator mStatusIconsAlphaAnimator;
private TouchAnimator mHeaderTextContainerAlphaAnimator;
- private TouchAnimator mPrivacyChipAlphaAnimator;
private DualToneHandler mDualToneHandler;
private View mSystemIconsView;
@@ -141,12 +127,7 @@
private View mRingerContainer;
private Clock mClockView;
private DateView mDateView;
- private OngoingPrivacyChip mPrivacyChip;
- private Space mSpace;
private BatteryMeterView mBatteryRemainingIcon;
- private boolean mPermissionsHubEnabled;
-
- private PrivacyItemController mPrivacyItemController;
private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
@Override
@@ -156,41 +137,17 @@
}
};
private boolean mHasTopCutout = false;
- private boolean mPrivacyChipLogged = false;
-
- private final DeviceConfig.OnPropertyChangedListener mPropertyListener =
- new DeviceConfig.OnPropertyChangedListener() {
- @Override
- public void onPropertyChanged(String namespace, String name, String value) {
- if (DeviceConfig.NAMESPACE_PRIVACY.equals(namespace)
- && SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED.equals(
- name)) {
- mPermissionsHubEnabled = Boolean.valueOf(value);
- StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
- iconContainer.setIgnoredSlots(getIgnoredIconSlots());
- }
- }
- };
-
- private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
- @Override
- public void privacyChanged(List<PrivacyItem> privacyItems) {
- mPrivacyChip.setPrivacyList(privacyItems);
- setChipVisibility(!privacyItems.isEmpty());
- }
- };
@Inject
public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
NextAlarmController nextAlarmController, ZenModeController zenModeController,
StatusBarIconController statusBarIconController,
- ActivityStarter activityStarter, PrivacyItemController privacyItemController) {
+ ActivityStarter activityStarter) {
super(context, attrs);
mAlarmController = nextAlarmController;
mZenController = zenModeController;
mStatusBarIconController = statusBarIconController;
mActivityStarter = activityStarter;
- mPrivacyItemController = privacyItemController;
mDualToneHandler = new DualToneHandler(
new ContextThemeWrapper(context, R.style.QSHeaderTheme));
}
@@ -203,8 +160,6 @@
mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
- // Ignore privacy icons because they show in the space above QQS
- iconContainer.addIgnoredSlots(getIgnoredIconSlots());
iconContainer.setShouldRestrictIcons(false);
mIconManager = new TintedIconManager(iconContainer);
@@ -218,9 +173,6 @@
mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
mRingerModeTextView = findViewById(R.id.ringer_mode_text);
mRingerContainer = findViewById(R.id.ringer_container);
- mRingerContainer.setOnClickListener(this::onClick);
- mPrivacyChip = findViewById(R.id.privacy_chip);
- mPrivacyChip.setOnClickListener(this::onClick);
mCarrierGroup = findViewById(R.id.carrier_group);
@@ -243,7 +195,6 @@
mClockView = findViewById(R.id.clock);
mClockView.setOnClickListener(this);
mDateView = findViewById(R.id.date);
- mSpace = findViewById(R.id.space);
// Tint for the battery icons are handled in setupHost()
mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
@@ -254,26 +205,6 @@
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
mRingerModeTextView.setSelected(true);
mNextAlarmTextView.setSelected(true);
-
- mPermissionsHubEnabled = PrivacyItemControllerKt.isPermissionsHubEnabled();
- // Change the ignored slots when DeviceConfig flag changes
- DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_PRIVACY,
- mContext.getMainExecutor(), mPropertyListener);
-
- }
-
- private List<String> getIgnoredIconSlots() {
- ArrayList<String> ignored = new ArrayList<>();
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_camera));
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_microphone));
- if (mPermissionsHubEnabled) {
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_location));
- }
-
- return ignored;
}
private void updateStatusText() {
@@ -287,21 +218,6 @@
}
}
- private void setChipVisibility(boolean chipVisible) {
- if (chipVisible && mPermissionsHubEnabled) {
- mPrivacyChip.setVisibility(View.VISIBLE);
- // Makes sure that the chip is logged as viewed at most once each time QS is opened
- // mListening makes sure that the callback didn't return after the user closed QS
- if (!mPrivacyChipLogged && mListening) {
- mPrivacyChipLogged = true;
- StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
- StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__CHIP_VIEWED);
- }
- } else {
- mPrivacyChip.setVisibility(View.GONE);
- }
- }
-
private boolean updateRingerStatus() {
boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
CharSequence originalRingerText = mRingerModeTextView.getText();
@@ -408,7 +324,6 @@
updateStatusIconAlphaAnimator();
updateHeaderTextContainerAlphaAnimator();
- updatePrivacyChipAlphaAnimator();
}
private void updateStatusIconAlphaAnimator() {
@@ -423,12 +338,6 @@
.build();
}
- private void updatePrivacyChipAlphaAnimator() {
- mPrivacyChipAlphaAnimator = new TouchAnimator.Builder()
- .addFloat(mPrivacyChip, "alpha", 1, 0, 1)
- .build();
- }
-
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -461,10 +370,11 @@
if (mHeaderTextContainerAlphaAnimator != null) {
mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
- }
- if (mPrivacyChipAlphaAnimator != null) {
- mPrivacyChip.setExpanded(expansionFraction > 0.5);
- mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
+ if (keyguardExpansionFraction > 0) {
+ mHeaderTextContainerView.setVisibility(VISIBLE);
+ } else {
+ mHeaderTextContainerView.setVisibility(INVISIBLE);
+ }
}
}
@@ -498,21 +408,6 @@
mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
}
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
- if (cutout != null) {
- Rect topCutout = cutout.getBoundingRectTop();
- if (topCutout.isEmpty()) {
- mHasTopCutout = false;
- lp.width = 0;
- mSpace.setVisibility(View.GONE);
- } else {
- mHasTopCutout = true;
- lp.width = topCutout.width();
- mSpace.setVisibility(View.VISIBLE);
- }
- }
- mSpace.setLayoutParams(lp);
- setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
return super.onApplyWindowInsets(insets);
}
@@ -537,13 +432,10 @@
mAlarmController.addCallback(this);
mContext.registerReceiver(mRingerReceiver,
new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
- mPrivacyItemController.addCallback(mPICCallback);
} else {
mZenController.removeCallback(this);
mAlarmController.removeCallback(this);
- mPrivacyItemController.removeCallback(mPICCallback);
mContext.unregisterReceiver(mRingerReceiver);
- mPrivacyChipLogged = false;
}
}
@@ -561,18 +453,6 @@
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
AlarmClock.ACTION_SHOW_ALARMS), 0);
}
- } else if (v == mPrivacyChip) {
- // Makes sure that the builder is grabbed as soon as the chip is pressed
- PrivacyDialogBuilder builder = mPrivacyChip.getBuilder();
- if (builder.getAppsAndTypes().size() == 0) return;
- Handler mUiHandler = new Handler(Looper.getMainLooper());
- StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
- StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__CHIP_CLICKED);
- mUiHandler.post(() -> {
- mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
- mHost.collapsePanels();
- });
} else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Settings.ACTION_SOUND_SETTINGS), 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index d202190..fc2705f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -294,17 +294,17 @@
int backgroundTop = 0;
int clipTopAmount = 0;
float firstElementRoundness = 0.0f;
- ExpandableNotificationRow previousRow = null;
+ ActivatableNotificationView previousRow = null;
for (int i = 0; i < mHostLayout.getChildCount(); i++) {
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
- if (!(child instanceof ExpandableNotificationRow)
- || child.getVisibility() == GONE) {
+ if (!(child instanceof ActivatableNotificationView)
+ || child.getVisibility() == GONE || child == this) {
continue;
}
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ ActivatableNotificationView row = (ActivatableNotificationView) child;
float notificationClipEnd;
boolean aboveShelf = ViewState.getFinalTranslationZ(row) > baseZHeight
|| row.isPinned();
@@ -324,43 +324,55 @@
}
int clipTop = updateNotificationClipHeight(row, notificationClipEnd, notGoneIndex);
clipTopAmount = Math.max(clipTop, clipTopAmount);
- float inShelfAmount = updateIconAppearance(row, expandAmount, scrolling, scrollingFast,
- expandingAnimated, isLastChild);
- numViewsInShelf += inShelfAmount;
- int ownColorUntinted = row.getBackgroundColorWithoutTint();
- if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) {
- mNotGoneIndex = notGoneIndex;
- setTintColor(previousColor);
- setOverrideTintColor(colorTwoBefore, transitionAmount);
- } else if (mNotGoneIndex == -1) {
- colorTwoBefore = previousColor;
- transitionAmount = inShelfAmount;
- }
- if (isLastChild) {
- if (colorOfViewBeforeLast == NO_COLOR) {
+ // If the current row is an ExpandableNotificationRow, update its color, roundedness,
+ // and icon state.
+ if (row instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow expandableRow = (ExpandableNotificationRow) row;
+
+ float inShelfAmount = updateIconAppearance(expandableRow, expandAmount, scrolling,
+ scrollingFast,
+ expandingAnimated, isLastChild);
+ numViewsInShelf += inShelfAmount;
+ int ownColorUntinted = row.getBackgroundColorWithoutTint();
+ if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) {
+ mNotGoneIndex = notGoneIndex;
+ setTintColor(previousColor);
+ setOverrideTintColor(colorTwoBefore, transitionAmount);
+
+ } else if (mNotGoneIndex == -1) {
+ colorTwoBefore = previousColor;
+ transitionAmount = inShelfAmount;
+ }
+ if (isLastChild) {
+ if (colorOfViewBeforeLast == NO_COLOR) {
+ colorOfViewBeforeLast = ownColorUntinted;
+ }
+ row.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount);
+ } else {
colorOfViewBeforeLast = ownColorUntinted;
+ row.setOverrideTintColor(NO_COLOR, 0 /* overrideAmount */);
}
- row.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount);
- } else {
- colorOfViewBeforeLast = ownColorUntinted;
- row.setOverrideTintColor(NO_COLOR, 0 /* overrideAmount */);
- }
- if (notGoneIndex != 0 || !aboveShelf) {
- row.setAboveShelf(false);
- }
- if (notGoneIndex == 0) {
- StatusBarIconView icon = row.getEntry().expandedIcon;
- NotificationIconContainer.IconState iconState = getIconState(icon);
- // The icon state might be null in rare cases where the notification is actually
- // added to the layout, but not to the shelf. An example are replied messages, since
- // they don't show up on AOD
- if (iconState != null && iconState.clampedAppearAmount == 1.0f) {
- // only if the first icon is fully in the shelf we want to clip to it!
- backgroundTop = (int) (row.getTranslationY() - getTranslationY());
- firstElementRoundness = row.getCurrentTopRoundness();
+ if (notGoneIndex != 0 || !aboveShelf) {
+ expandableRow.setAboveShelf(false);
}
+ if (notGoneIndex == 0) {
+ StatusBarIconView icon = expandableRow.getEntry().expandedIcon;
+ NotificationIconContainer.IconState iconState = getIconState(icon);
+ // The icon state might be null in rare cases where the notification is actually
+ // added to the layout, but not to the shelf. An example are replied messages,
+ // since they don't show up on AOD
+ if (iconState != null && iconState.clampedAppearAmount == 1.0f) {
+ // only if the first icon is fully in the shelf we want to clip to it!
+ backgroundTop = (int) (row.getTranslationY() - getTranslationY());
+ firstElementRoundness = row.getCurrentTopRoundness();
+ }
+ }
+
+ previousColor = ownColorUntinted;
+ notGoneIndex++;
}
+
if (row.isFirstInSection() && previousRow != null && previousRow.isLastInSection()) {
// If the top of the shelf is between the view before a gap and the view after a gap
// then we need to adjust the shelf's top roundness.
@@ -379,8 +391,6 @@
backgroundTop = (int) distanceToGapBottom;
}
}
- notGoneIndex++;
- previousColor = ownColorUntinted;
previousRow = row;
}
clipTransientViews();
@@ -497,7 +507,7 @@
* Update the clipping of this view.
* @return the amount that our own top should be clipped
*/
- private int updateNotificationClipHeight(ExpandableNotificationRow row,
+ private int updateNotificationClipHeight(ActivatableNotificationView row,
float notificationClipEnd, int childIndex) {
float viewEnd = row.getTranslationY() + row.getActualHeight();
boolean isPinned = (row.isPinned() || row.isHeadsUpAnimatingAway())
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
index b89b5cb..5378f90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -43,6 +43,18 @@
const val TAG = "ChannelDialogController"
+/**
+ * ChannelEditorDialogController is the controller for the dialog half-shelf
+ * that allows users to quickly turn off channels. It is launched from the NotificationInfo
+ * guts view and displays controls for toggling app notifications as well as up to 4 channels
+ * from that app like so:
+ *
+ * APP TOGGLE <on/off>
+ * - Channel from which we launched <on/off>
+ * - <on/off>
+ * - the next 3 channels sorted alphabetically for that app <on/off>
+ * - <on/off>
+ */
@Singleton
class ChannelEditorDialogController @Inject constructor(
c: Context,
@@ -58,6 +70,9 @@
private var appName: String? = null
private var onSettingsClickListener: NotificationInfo.OnSettingsClickListener? = null
+ // Caller should set this if they care about when we dismiss
+ var onFinishListener: OnChannelEditorDialogFinishedListener? = null
+
// Channels handed to us from NotificationInfo
@VisibleForTesting
internal val providedChannels = mutableListOf<NotificationChannel>()
@@ -144,6 +159,7 @@
private fun done() {
resetState()
dialog.dismiss()
+ onFinishListener?.onChannelEditorDialogFinished()
}
private fun resetState() {
@@ -223,6 +239,8 @@
dialog = Dialog(context)
dialog.window?.requestFeature(Window.FEATURE_NO_TITLE)
+ // Prevent a11y readers from reading the first element in the dialog twice
+ dialog.setTitle("\u00A0")
dialog.apply {
setContentView(R.layout.notif_half_shelf)
setCanceledOnTouchOutside(true)
@@ -240,7 +258,7 @@
findViewById<TextView>(R.id.see_more_button)?.setOnClickListener {
onSettingsClickListener?.onClick(it, null, appUid!!)
- dismiss()
+ done()
}
window?.apply {
@@ -265,3 +283,7 @@
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
}
+
+interface OnChannelEditorDialogFinishedListener {
+ fun onChannelEditorDialogFinished()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
index 4d49760..6fe1477 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
@@ -143,7 +143,7 @@
private fun updateViews() {
val nc = channel ?: return
- channelName.text = nc.name ?: "(missing)"
+ channelName.text = nc.name ?: ""
nc.group?.let { groupId ->
channelDescription.text = controller.groupNameForId(groupId)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 1dc96b8..626701c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -159,13 +159,13 @@
// used by standard ui
private OnClickListener mOnDismissSettings = v -> {
mPressedApply = true;
- closeControls(v);
+ closeControls(v, true);
};
// used by blocking helper
private OnClickListener mOnKeepShowing = v -> {
mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
- closeControls(v);
+ closeControls(v, true);
mMetricsLogger.write(getLogMaker().setCategory(
MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
.setType(MetricsEvent.TYPE_ACTION)
@@ -445,6 +445,8 @@
if (mChannelEditorDialogController != null) {
mChannelEditorDialogController.prepareDialogForApp(mAppName, mPackageName, mAppUid,
mUniqueChannelsInRow, mPkgIcon, mOnSettingsClickListener);
+ mChannelEditorDialogController.setOnFinishListener(
+ () -> closeControls(this, false));
mChannelEditorDialogController.show();
}
});
@@ -725,7 +727,7 @@
* {@link #swapContent(boolean, boolean)} for where undo is handled.
*/
@VisibleForTesting
- void closeControls(View v) {
+ void closeControls(View v, boolean save) {
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
mGutsContainer.getLocationOnScreen(parentLoc);
@@ -734,7 +736,7 @@
final int centerY = v.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
+ mGutsContainer.closeControls(x, y, save, false /* force */);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 4526eaf..20e8b73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -18,6 +18,7 @@
import static com.android.systemui.Dependency.MAIN_HANDLER;
+import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -28,7 +29,6 @@
import android.metrics.LogMaker;
import android.os.Handler;
import android.text.format.DateUtils;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewStub;
@@ -52,7 +52,6 @@
*/
public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper {
- private static final String TAG = "NotificationMediaTVW";
private static final long PROGRESS_UPDATE_INTERVAL = 1000; // 1s
private static final String COMPACT_MEDIA_TAG = "media";
private final Handler mHandler = Dependency.get(MAIN_HANDLER);
@@ -63,6 +62,7 @@
private TextView mSeekBarTotalTime;
private long mDuration = 0;
private MediaController mMediaController;
+ private MediaMetadata mMediaMetadata;
private NotificationMediaManager mMediaManager;
private View mSeekBarView;
private Context mContext;
@@ -81,7 +81,7 @@
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
- if (mMediaController != null && canSeekMedia()) {
+ if (mMediaController != null) {
mMediaController.getTransportControls().seekTo(mSeekBar.getProgress());
mMetricsLogger.write(newLog(MetricsEvent.TYPE_UPDATE));
}
@@ -96,16 +96,28 @@
}
@Override
- public void onPlaybackStateChanged(PlaybackState state) {
+ public void onPlaybackStateChanged(@Nullable PlaybackState state) {
+ if (state == null) {
+ return;
+ }
+
if (state.getState() != PlaybackState.STATE_PLAYING) {
// Update the UI once, in case playback info changed while we were paused
- mUpdatePlaybackUi.run();
+ updatePlaybackUi(state);
clearTimer();
} else if (mSeekBarTimer == null && mSeekBarView != null
&& mSeekBarView.getVisibility() != View.GONE) {
startTimer();
}
}
+
+ @Override
+ public void onMetadataChanged(@Nullable MediaMetadata metadata) {
+ if (mMediaMetadata == null || !mMediaMetadata.equals(metadata)) {
+ mMediaMetadata = metadata;
+ updateDuration();
+ }
+ }
};
protected NotificationMediaTemplateViewWrapper(Context ctx, View view,
@@ -140,12 +152,11 @@
controllerUpdated = true;
}
- if (mMediaController.getMetadata() != null) {
- long duration = mMediaController.getMetadata().getLong(
- MediaMetadata.METADATA_KEY_DURATION);
+ mMediaMetadata = mMediaController.getMetadata();
+ if (mMediaMetadata != null) {
+ long duration = mMediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
if (duration <= 0) {
// Don't include the seekbar if this is a livestream
- Log.d(TAG, "removing seekbar");
if (mSeekBarView != null && mSeekBarView.getVisibility() != View.GONE) {
mSeekBarView.setVisibility(View.GONE);
mMetricsLogger.write(newLog(MetricsEvent.TYPE_CLOSE));
@@ -156,12 +167,12 @@
mMetricsLogger.write(newLog(MetricsEvent.TYPE_CLOSE));
}
return;
- } else {
+ } else if (mSeekBarView != null && mSeekBarView.getVisibility() == View.GONE) {
// Otherwise, make sure the seekbar is visible
- if (mSeekBarView != null && mSeekBarView.getVisibility() == View.GONE) {
- mSeekBarView.setVisibility(View.VISIBLE);
- mMetricsLogger.write(newLog(MetricsEvent.TYPE_OPEN));
- }
+ mSeekBarView.setVisibility(View.VISIBLE);
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_OPEN));
+ updateDuration();
+ startTimer();
}
}
@@ -181,13 +192,13 @@
mSeekBarTotalTime = mSeekBarView.findViewById(R.id.notification_media_total_time);
if (mSeekBarTimer == null) {
- if (canSeekMedia()) {
+ if (mMediaController != null && canSeekMedia(mMediaController.getPlaybackState())) {
// Log initial state, since it will not be updated
mMetricsLogger.write(newLog(MetricsEvent.TYPE_DETAIL, 1));
} else {
setScrubberVisible(false);
}
-
+ updateDuration();
startTimer();
mMediaController.registerCallback(mMediaCallback);
}
@@ -201,7 +212,7 @@
mSeekBarTimer.schedule(new TimerTask() {
@Override
public void run() {
- mHandler.post(mUpdatePlaybackUi);
+ mHandler.post(mOnUpdateTimerTick);
}
}, 0, PROGRESS_UPDATE_INTERVAL);
}
@@ -215,14 +226,12 @@
}
}
- private boolean canSeekMedia() {
- if (mMediaController == null || mMediaController.getPlaybackState() == null) {
- Log.d(TAG, "Cannot seek media because the controller is invalid");
+ private boolean canSeekMedia(@Nullable PlaybackState state) {
+ if (state == null) {
return false;
}
- long actions = mMediaController.getPlaybackState().getActions();
- Log.d(TAG, "Playback state actions are " + actions);
+ long actions = state.getActions();
return ((actions & PlaybackState.ACTION_SEEK_TO) != 0);
}
@@ -236,39 +245,44 @@
mMetricsLogger.write(newLog(MetricsEvent.TYPE_DETAIL, isVisible ? 1 : 0));
}
- protected final Runnable mUpdatePlaybackUi = new Runnable() {
+ private void updateDuration() {
+ if (mMediaMetadata != null && mSeekBar != null) {
+ long duration = mMediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
+ if (mDuration != duration) {
+ mDuration = duration;
+ mSeekBar.setMax((int) mDuration);
+ mSeekBarTotalTime.setText(millisecondsToTimeString(duration));
+ }
+ }
+ }
+
+ protected final Runnable mOnUpdateTimerTick = new Runnable() {
@Override
public void run() {
if (mMediaController != null && mSeekBar != null) {
- MediaMetadata metadata = mMediaController.getMetadata();
PlaybackState playbackState = mMediaController.getPlaybackState();
- if (metadata != null && playbackState != null) {
- long position = playbackState.getPosition();
- long duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
-
- if (mDuration != duration) {
- mDuration = duration;
- mSeekBar.setMax((int) mDuration);
- mSeekBarTotalTime.setText(millisecondsToTimeString(duration));
- }
- mSeekBar.setProgress((int) position);
-
- mSeekBarElapsedTime.setText(millisecondsToTimeString(position));
-
- // Update scrubber in case available actions have changed
- setScrubberVisible(canSeekMedia());
+ if (playbackState != null) {
+ updatePlaybackUi(playbackState);
} else {
- Log.d(TAG, "Controller missing data " + metadata + " " + playbackState);
clearTimer();
}
} else {
- Log.d(TAG, "No longer have a valid media controller");
clearTimer();
}
}
};
+ private void updatePlaybackUi(PlaybackState state) {
+ long position = state.getPosition();
+ mSeekBar.setProgress((int) position);
+
+ mSeekBarElapsedTime.setText(millisecondsToTimeString(position));
+
+ // Update scrubber in case available actions have changed
+ setScrubberVisible(canSeekMedia(state));
+ }
+
private String millisecondsToTimeString(long milliseconds) {
long seconds = milliseconds / 1000;
String text = DateUtils.formatElapsedTime(seconds);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index ee43879..17c200e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -42,10 +42,6 @@
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.UiOffloadThread;
-import com.android.systemui.privacy.PrivacyItem;
-import com.android.systemui.privacy.PrivacyItemController;
-import com.android.systemui.privacy.PrivacyItemControllerKt;
-import com.android.systemui.privacy.PrivacyType;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.statusbar.CommandQueue;
@@ -66,9 +62,6 @@
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.List;
import java.util.Locale;
/**
@@ -83,12 +76,12 @@
ZenModeController.Callback,
DeviceProvisionedListener,
KeyguardMonitor.Callback,
- PrivacyItemController.Callback,
LocationController.LocationChangeCallback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final int LOCATION_STATUS_ICON_ID = PrivacyType.TYPE_LOCATION.getIconId();
+ public static final int LOCATION_STATUS_ICON_ID =
+ com.android.internal.R.drawable.perm_group_location;
private final String mSlotCast;
private final String mSlotHotspot;
@@ -102,8 +95,6 @@
private final String mSlotHeadset;
private final String mSlotDataSaver;
private final String mSlotLocation;
- private final String mSlotMicrophone;
- private final String mSlotCamera;
private final String mSlotSensorsOff;
private final Context mContext;
@@ -121,7 +112,6 @@
private final DeviceProvisionedController mProvisionedController;
private final KeyguardMonitor mKeyguardMonitor;
private final LocationController mLocationController;
- private final PrivacyItemController mPrivacyItemController;
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
private final SensorPrivacyController mSensorPrivacyController;
@@ -154,7 +144,6 @@
mProvisionedController = Dependency.get(DeviceProvisionedController.class);
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mLocationController = Dependency.get(LocationController.class);
- mPrivacyItemController = Dependency.get(PrivacyItemController.class);
mSensorPrivacyController = Dependency.get(SensorPrivacyController.class);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
@@ -170,8 +159,6 @@
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
- mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
- mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
mSlotSensorsOff = context.getString(com.android.internal.R.string.status_bar_sensors_off);
// listen for broadcasts
@@ -231,13 +218,6 @@
context.getString(R.string.accessibility_data_saver_on));
mIconController.setIconVisibility(mSlotDataSaver, false);
- // privacy items
- mIconController.setIcon(mSlotMicrophone, PrivacyType.TYPE_MICROPHONE.getIconId(),
- PrivacyType.TYPE_MICROPHONE.getName(mContext));
- mIconController.setIconVisibility(mSlotMicrophone, false);
- mIconController.setIcon(mSlotCamera, PrivacyType.TYPE_CAMERA.getIconId(),
- PrivacyType.TYPE_CAMERA.getName(mContext));
- mIconController.setIconVisibility(mSlotCamera, false);
mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
mContext.getString(R.string.accessibility_location_active));
mIconController.setIconVisibility(mSlotLocation, false);
@@ -257,7 +237,6 @@
mNextAlarmController.addCallback(mNextAlarmCallback);
mDataSaver.addCallback(this);
mKeyguardMonitor.addCallback(this);
- mPrivacyItemController.addCallback(this);
mSensorPrivacyController.addCallback(mSensorPrivacyListener);
mLocationController.addCallback(this);
@@ -601,46 +580,9 @@
mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
}
- @Override // PrivacyItemController.Callback
- public void privacyChanged(List<PrivacyItem> privacyItems) {
- updatePrivacyItems(privacyItems);
- }
-
- private void updatePrivacyItems(List<PrivacyItem> items) {
- boolean showCamera = false;
- boolean showMicrophone = false;
- boolean showLocation = false;
- for (PrivacyItem item : items) {
- if (item == null /* b/124234367 */) {
- if (DEBUG) {
- Log.e(TAG, "updatePrivacyItems - null item found");
- StringWriter out = new StringWriter();
- mPrivacyItemController.dump(null, new PrintWriter(out), null);
- Log.e(TAG, out.toString());
- }
- continue;
- }
- switch (item.getPrivacyType()) {
- case TYPE_CAMERA:
- showCamera = true;
- break;
- case TYPE_LOCATION:
- showLocation = true;
- break;
- case TYPE_MICROPHONE:
- showMicrophone = true;
- break;
- }
- }
-
- mIconController.setIconVisibility(mSlotCamera, showCamera);
- mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
- mIconController.setIconVisibility(mSlotLocation, showLocation);
- }
-
@Override
public void onLocationActiveChanged(boolean active) {
- if (!PrivacyItemControllerKt.isPermissionsHubEnabled()) updateLocation();
+ updateLocation();
}
// Updates the status view based on the current state of location requests.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index f726321..395add7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -111,7 +111,9 @@
public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@Named(MAIN_HANDLER_NAME) Handler handler, ActivityStarter activityStarter) {
mContext = context;
- mGuestResumeSessionReceiver.register(context);
+ if (!UserManager.isGuestUserEphemeral()) {
+ mGuestResumeSessionReceiver.register(context);
+ }
mKeyguardMonitor = keyguardMonitor;
mHandler = handler;
mActivityStarter = activityStarter;
diff --git a/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java b/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java
index d9d410d..09dbfee 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java
@@ -49,6 +49,11 @@
}
@Override
+ protected void onFinishInflate() {
+ onVisibilityAggregated(isVisibleToUser());
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSelected(true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index db45ad78..fa81e40 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -27,6 +27,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -36,6 +37,7 @@
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
+import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -43,6 +45,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.R;
import com.android.internal.telephony.IccCardConstants;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
@@ -56,7 +59,6 @@
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
@SmallTest
@@ -68,6 +70,7 @@
private static final String TEST_CARRIER = "TEST_CARRIER";
private static final String TEST_CARRIER_2 = "TEST_CARRIER_2";
private static final String TEST_GROUP_UUID = "59b5c870-fc4c-47a4-a99e-9db826b48b24";
+ private static final String EMERGENCY = "Emergency";
private static final int TEST_CARRIER_ID = 1;
private static final SubscriptionInfo TEST_SUBSCRIPTION = new SubscriptionInfo(0, "", 0,
TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "",
@@ -106,6 +109,8 @@
mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
mContext.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.string.emergency_calls_only, EMERGENCY);
mDependency.injectMockDependency(WakefulnessLifecycle.class);
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
new Handler(mTestableLooper.getLooper()));
@@ -190,8 +195,6 @@
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
-
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -214,8 +217,6 @@
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
-
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -259,8 +260,6 @@
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
-
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -284,8 +283,6 @@
.thenReturn(IccCardConstants.State.NOT_READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
-
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -309,8 +306,6 @@
.thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
-
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -335,7 +330,6 @@
.thenReturn(IccCardConstants.State.NOT_READY)
.thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
@@ -358,7 +352,6 @@
when(mKeyguardUpdateMonitor.getSimState(anyInt()))
.thenReturn(IccCardConstants.State.READY);
- mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
mCarrierTextController.updateDisplayOpportunisticSubscriptionCarrierText(true);
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
@@ -373,6 +366,127 @@
assertEquals(TEST_CARRIER_2, captor.getValue().carrierText);
}
+ @Test
+ public void testCarrierText_replaceOutOfServiceWithEmergency() {
+ reset(mCarrierTextCallback);
+
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY);
+ ServiceState s = mock(ServiceState.class);
+ when(mKeyguardUpdateMonitor.getServiceState(anyInt())).thenReturn(s);
+ when(s.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+
+ when(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).thenReturn(true);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(1, captor.getValue().listOfCarriers.length);
+ assertEquals(EMERGENCY, captor.getValue().listOfCarriers[0]);
+ }
+
+ @Test
+ public void testCarrierText_replaceOutOfServiceWithEmergencyOnlyInNoService() {
+ reset(mCarrierTextCallback);
+
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION_2);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY);
+ ServiceState sInService = mock(ServiceState.class);
+ ServiceState sOutOfService = mock(ServiceState.class);
+ when(mKeyguardUpdateMonitor.getServiceState(anyInt()))
+ .thenReturn(sInService)
+ .thenReturn(sOutOfService);
+ when(sInService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(sOutOfService.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+
+ when(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).thenReturn(true);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(2, captor.getValue().listOfCarriers.length);
+ assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+ assertEquals(EMERGENCY, captor.getValue().listOfCarriers[1]);
+ }
+
+ @Test
+ public void testCarrierText_dontReplaceWithEmergencyIfNotAble() {
+ reset(mCarrierTextCallback);
+
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION_2);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY);
+ ServiceState sOutOfService = mock(ServiceState.class);
+ when(mKeyguardUpdateMonitor.getServiceState(anyInt())).thenReturn(sOutOfService);
+ when(sOutOfService.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+
+ when(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).thenReturn(false);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(2, captor.getValue().listOfCarriers.length);
+ assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+ assertEquals(TEST_CARRIER_2, captor.getValue().listOfCarriers[1]);
+ }
+
+ @Test
+ public void testCarrierText_dontReplaceWithEmergencyIfAlreadyEmergency() {
+ reset(mCarrierTextCallback);
+
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY);
+ ServiceState sOutOfService = mock(ServiceState.class);
+ when(mKeyguardUpdateMonitor.getServiceState(anyInt())).thenReturn(sOutOfService);
+ when(sOutOfService.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(sOutOfService.isEmergencyOnly()).thenReturn(true);
+
+ when(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).thenReturn(false);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(1, captor.getValue().listOfCarriers.length);
+ assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+ }
+
public static class TestCarrierTextController extends CarrierTextController {
private KeyguardUpdateMonitor mKUM;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 6208ab8..3a3cbad 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -22,6 +22,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -361,6 +362,52 @@
assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
}
+ @Test
+ public void testAnySimEmergency_allSimsInService() {
+ ServiceState s0 = mock(ServiceState.class);
+ when(s0.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 0, s0);
+ assertThat(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).isTrue();
+ }
+
+ @Test
+ public void testAnySimEmergency_someSimsInServiceOthersNotECC() {
+ ServiceState s0 = mock(ServiceState.class);
+ when(s0.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ ServiceState s1 = mock(ServiceState.class);
+ when(s1.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 0, s0);
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 1, s1);
+ assertThat(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).isTrue();
+ }
+
+ @Test
+ public void testAnySimEmergency_someSimsEmergencyCapable() {
+ ServiceState s0 = mock(ServiceState.class);
+ when(s0.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+ ServiceState s1 = mock(ServiceState.class);
+ when(s1.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(s1.isEmergencyOnly()).thenReturn(true);
+
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 0, s0);
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 1, s1);
+ assertThat(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).isTrue();
+ }
+
+ @Test
+ public void testAnySimEmergency_noEmergencyCapable() {
+ ServiceState s0 = mock(ServiceState.class);
+ when(s0.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+ ServiceState s1 = mock(ServiceState.class);
+ when(s1.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 0, s0);
+ mKeyguardUpdateMonitor.handleServiceStateChange(0, 1, s1);
+ assertThat(mKeyguardUpdateMonitor.isAnySimEmergencyAble()).isFalse();
+ }
+
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index cc31531..bd7f897 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -25,11 +25,9 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.content.pm.PackageManager;
@@ -55,7 +53,6 @@
private static final String TEST_PACKAGE_NAME = "test";
private static final int TEST_UID = UserHandle.getUid(0, 0);
private static final int TEST_UID_OTHER = UserHandle.getUid(1, 0);
- private static final int TEST_UID_NON_USER_SENSITIVE = UserHandle.getUid(2, 0);
@Mock
private AppOpsManager mAppOpsManager;
@@ -74,18 +71,6 @@
getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
- // All permissions of TEST_UID and TEST_UID_OTHER are user sensitive. None of
- // TEST_UID_NON_USER_SENSITIVE are user sensitive.
- getContext().setMockPackageManager(mPackageManager);
- when(mPackageManager.getPermissionFlags(anyString(), anyString(),
- eq(UserHandle.getUserHandleForUid(TEST_UID)))).thenReturn(
- PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED);
- when(mPackageManager.getPermissionFlags(anyString(), anyString(),
- eq(UserHandle.getUserHandleForUid(TEST_UID_OTHER)))).thenReturn(
- PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED);
- when(mPackageManager.getPermissionFlags(anyString(), anyString(),
- eq(UserHandle.getUserHandleForUid(TEST_UID_NON_USER_SENSITIVE)))).thenReturn(0);
-
mController = new AppOpsControllerImpl(mContext, Dependency.get(Dependency.BG_LOOPER));
}
@@ -178,14 +163,6 @@
}
@Test
- public void nonUserSensitiveOpsAreIgnored() {
- mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
- TEST_UID_NON_USER_SENSITIVE, TEST_PACKAGE_NAME, true);
- assertEquals(0, mController.getActiveAppOpsForUser(
- UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size());
- }
-
- @Test
public void opNotedScheduledForRemoval() {
mController.setBGHandler(mMockHandler);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
index 67df60a..9c2c822 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -36,8 +37,10 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
/**
* Tests color extraction generation.
@@ -54,62 +57,68 @@
ColorExtractor.TYPE_DARK,
ColorExtractor.TYPE_EXTRA_DARK};
+ private ColorExtractor.GradientColors mColors;
+ private SysuiColorExtractor mColorExtractor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mColors = new ColorExtractor.GradientColors();
+ mColors.setMainColor(Color.RED);
+ mColors.setSecondaryColor(Color.RED);
+ mColorExtractor = new SysuiColorExtractor(getContext(),
+ (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
+ outGradientColorsExtraDark) -> {
+ outGradientColorsNormal.set(mColors);
+ outGradientColorsDark.set(mColors);
+ outGradientColorsExtraDark.set(mColors);
+ }, mock(ConfigurationController.class), false);
+ }
+
@Test
public void getColors_usesGreyIfWallpaperNotVisible() {
- ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors();
- colors.setMainColor(Color.RED);
- colors.setSecondaryColor(Color.RED);
+ simulateEvent(mColorExtractor);
+ mColorExtractor.setWallpaperVisible(false);
- SysuiColorExtractor extractor = getTestableExtractor(colors);
- simulateEvent(extractor);
- extractor.setWallpaperVisible(false);
-
- ColorExtractor.GradientColors fallbackColors = extractor.getNeutralColors();
+ ColorExtractor.GradientColors fallbackColors = mColorExtractor.getNeutralColors();
for (int type : sTypes) {
assertEquals("Not using fallback!",
- extractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
assertNotEquals("Wallpaper visibility event should not affect lock wallpaper.",
- extractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
}
}
@Test
public void getColors_doesntUseFallbackIfVisible() {
- ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors();
- colors.setMainColor(Color.RED);
- colors.setSecondaryColor(Color.RED);
+ mColors.setMainColor(Color.RED);
+ mColors.setSecondaryColor(Color.RED);
- SysuiColorExtractor extractor = getTestableExtractor(colors);
- simulateEvent(extractor);
- extractor.setWallpaperVisible(true);
+ simulateEvent(mColorExtractor);
+ mColorExtractor.setWallpaperVisible(true);
for (int which : sWhich) {
for (int type : sTypes) {
assertEquals("Not using extracted colors!",
- extractor.getColors(which, type), colors);
+ mColorExtractor.getColors(which, type), mColors);
}
}
}
@Test
public void getColors_fallbackWhenMediaIsVisible() {
- ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors();
- colors.setMainColor(Color.RED);
- colors.setSecondaryColor(Color.RED);
+ simulateEvent(mColorExtractor);
+ mColorExtractor.setWallpaperVisible(true);
+ mColorExtractor.setHasBackdrop(true);
- SysuiColorExtractor extractor = getTestableExtractor(colors);
- simulateEvent(extractor);
- extractor.setWallpaperVisible(true);
- extractor.setHasBackdrop(true);
-
- ColorExtractor.GradientColors fallbackColors = extractor.getNeutralColors();
+ ColorExtractor.GradientColors fallbackColors = mColorExtractor.getNeutralColors();
for (int type : sTypes) {
assertEquals("Not using fallback!",
- extractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
assertNotEquals("Media visibility should not affect system wallpaper.",
- extractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
}
}
@@ -126,14 +135,13 @@
verify(tonal).applyFallback(any(), any());
}
- private SysuiColorExtractor getTestableExtractor(ColorExtractor.GradientColors colors) {
- return new SysuiColorExtractor(getContext(),
- (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
- outGradientColorsExtraDark) -> {
- outGradientColorsNormal.set(colors);
- outGradientColorsDark.set(colors);
- outGradientColorsExtraDark.set(colors);
- }, mock(ConfigurationController.class), false);
+ @Test
+ public void onUiModeChanged_notifiesListener() {
+ ColorExtractor.OnColorsChangedListener listener = mock(
+ ColorExtractor.OnColorsChangedListener.class);
+ mColorExtractor.addOnColorsChangedListener(listener);
+ mColorExtractor.onUiModeChanged();
+ verify(listener).onColorsChanged(any(), anyInt());
}
private void simulateEvent(SysuiColorExtractor extractor) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
deleted file mode 100644
index 6302f9d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
+++ /dev/null
@@ -1,77 +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.privacy
-
-import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
-import com.android.systemui.SysuiTestCase
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class PrivacyDialogBuilderTest : SysuiTestCase() {
-
- companion object {
- val TEST_UID = 1
- }
-
- @Test
- fun testGenerateAppsList() {
- val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Bar", TEST_UID, context))
- val bar3 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication(
- "Bar", TEST_UID, context))
- val foo0 = PrivacyItem(Privacy.TYPE_MICROPHONE, PrivacyApplication(
- "Foo", TEST_UID, context))
- val baz1 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Baz", TEST_UID, context))
-
- val items = listOf(bar2, foo0, baz1, bar3)
-
- val textBuilder = PrivacyDialogBuilder(context, items)
-
- val list = textBuilder.appsAndTypes
- assertEquals(3, list.size)
- val appsList = list.map { it.first }
- val typesList = list.map { it.second }
- // List is sorted by number of types and then by types
- assertEquals(listOf("Bar", "Baz", "Foo"), appsList.map { it.packageName })
- assertEquals(listOf(Privacy.TYPE_CAMERA, Privacy.TYPE_LOCATION), typesList[0])
- assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[1])
- assertEquals(listOf(Privacy.TYPE_MICROPHONE), typesList[2])
- }
-
- @Test
- fun testOrder() {
- // We want location to always go last, so it will go in the "+ other apps"
- val appCamera = PrivacyItem(PrivacyType.TYPE_CAMERA,
- PrivacyApplication("Camera", TEST_UID, context))
- val appMicrophone =
- PrivacyItem(PrivacyType.TYPE_MICROPHONE,
- PrivacyApplication("Microphone", TEST_UID, context))
- val appLocation =
- PrivacyItem(PrivacyType.TYPE_LOCATION,
- PrivacyApplication("Location", TEST_UID, context))
-
- val items = listOf(appLocation, appMicrophone, appCamera)
- val textBuilder = PrivacyDialogBuilder(context, items)
- val appList = textBuilder.appsAndTypes.map { it.first }.map { it.packageName }
- assertEquals(listOf("Camera", "Microphone", "Location"), appList)
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
deleted file mode 100644
index e2e0bb1..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ /dev/null
@@ -1,293 +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.privacy
-
-import android.app.ActivityManager
-import android.app.AppOpsManager
-import android.content.Context
-import android.content.Intent
-import android.content.pm.UserInfo
-import android.os.Handler
-import android.os.UserHandle
-import android.os.UserManager
-import android.provider.DeviceConfig
-import android.provider.Settings.RESET_MODE_PACKAGE_DEFAULTS
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-import com.android.systemui.Dependency
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.appops.AppOpItem
-import com.android.systemui.appops.AppOpsController
-import org.hamcrest.Matchers.hasItem
-import org.hamcrest.Matchers.not
-import org.hamcrest.Matchers.nullValue
-import org.junit.After
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertThat
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyList
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-@RunWithLooper
-class PrivacyItemControllerTest : SysuiTestCase() {
-
- companion object {
- val CURRENT_USER_ID = ActivityManager.getCurrentUser()
- val TEST_UID = CURRENT_USER_ID * UserHandle.PER_USER_RANGE
- const val SYSTEM_UID = 1000
- const val TEST_PACKAGE_NAME = "test"
- const val DEVICE_SERVICES_STRING = "Device services"
- const val TAG = "PrivacyItemControllerTest"
- fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
- }
-
- @Mock
- private lateinit var appOpsController: AppOpsController
- @Mock
- private lateinit var callback: PrivacyItemController.Callback
- @Mock
- private lateinit var userManager: UserManager
- @Captor
- private lateinit var argCaptor: ArgumentCaptor<List<PrivacyItem>>
- @Captor
- private lateinit var argCaptorCallback: ArgumentCaptor<AppOpsController.Callback>
-
- private lateinit var testableLooper: TestableLooper
- private lateinit var privacyItemController: PrivacyItemController
- private lateinit var handler: Handler
-
- fun PrivacyItemController(context: Context) =
- PrivacyItemController(context, appOpsController, handler, handler)
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- testableLooper = TestableLooper.get(this)
- handler = Handler(testableLooper.looper)
-
- appOpsController = mDependency.injectMockDependency(AppOpsController::class.java)
- mDependency.injectTestDependency(Dependency.BG_HANDLER, handler)
- mDependency.injectTestDependency(Dependency.MAIN_HANDLER, handler)
- mContext.addMockSystemService(UserManager::class.java, userManager)
- mContext.getOrCreateTestableResources().addOverride(R.string.device_services,
- DEVICE_SERVICES_STRING)
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED,
- "true", false)
-
- doReturn(listOf(object : UserInfo() {
- init {
- id = CURRENT_USER_ID
- }
- })).`when`(userManager).getProfiles(anyInt())
-
- privacyItemController = PrivacyItemController(mContext)
- }
-
- @After
- fun tearDown() {
- DeviceConfig.resetToDefaults(RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_PRIVACY)
- }
-
- @Test
- fun testSetListeningTrueByAddingCallback() {
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(appOpsController).addCallback(eq(PrivacyItemController.OPS),
- any(AppOpsController.Callback::class.java))
- testableLooper.processAllMessages()
- verify(callback).privacyChanged(anyList())
- }
-
- @Test
- fun testSetListeningFalseByRemovingLastCallback() {
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(appOpsController, never()).removeCallback(any(IntArray::class.java),
- any(AppOpsController.Callback::class.java))
- privacyItemController.removeCallback(callback)
- testableLooper.processAllMessages()
- verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
- any(AppOpsController.Callback::class.java))
- verify(callback).privacyChanged(emptyList())
- }
-
- @Test
- fun testDistinctItems() {
- doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
- AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1)))
- .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
-
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(callback).privacyChanged(capture(argCaptor))
- assertEquals(1, argCaptor.value.size)
- }
-
- @Test
- fun testSystemApps() {
- doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, SYSTEM_UID, TEST_PACKAGE_NAME,
- 0))).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(callback).privacyChanged(capture(argCaptor))
- assertEquals(1, argCaptor.value.size)
- assertEquals(context.getString(R.string.device_services),
- argCaptor.value[0].application.applicationName)
- }
-
- @Test
- fun testRegisterReceiver_allUsers() {
- val spiedContext = spy(mContext)
- val itemController = PrivacyItemController(spiedContext)
- itemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(spiedContext, atLeastOnce()).registerReceiverAsUser(
- eq(itemController.userSwitcherReceiver), eq(UserHandle.ALL), any(), eq(null),
- eq(null))
- verify(spiedContext, never()).unregisterReceiver(eq(itemController.userSwitcherReceiver))
- }
-
- @Test
- fun testReceiver_ACTION_USER_FOREGROUND() {
- privacyItemController.userSwitcherReceiver.onReceive(context,
- Intent(Intent.ACTION_USER_FOREGROUND))
- verify(userManager).getProfiles(anyInt())
- }
-
- @Test
- fun testReceiver_ACTION_MANAGED_PROFILE_ADDED() {
- privacyItemController.userSwitcherReceiver.onReceive(context,
- Intent(Intent.ACTION_MANAGED_PROFILE_ADDED))
- verify(userManager).getProfiles(anyInt())
- }
-
- @Test
- fun testReceiver_ACTION_MANAGED_PROFILE_REMOVED() {
- privacyItemController.userSwitcherReceiver.onReceive(context,
- Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED))
- verify(userManager).getProfiles(anyInt())
- }
-
- @Test
- fun testAddMultipleCallbacks() {
- val otherCallback = mock(PrivacyItemController.Callback::class.java)
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(callback).privacyChanged(anyList())
-
- privacyItemController.addCallback(otherCallback)
- testableLooper.processAllMessages()
- verify(otherCallback).privacyChanged(anyList())
- // Adding a callback should not unnecessarily call previous ones
- verifyNoMoreInteractions(callback)
- }
-
- @Test
- fun testMultipleCallbacksAreUpdated() {
- doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
-
- val otherCallback = mock(PrivacyItemController.Callback::class.java)
- privacyItemController.addCallback(callback)
- privacyItemController.addCallback(otherCallback)
- testableLooper.processAllMessages()
- reset(callback)
- reset(otherCallback)
-
- verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback))
- argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true)
- testableLooper.processAllMessages()
- verify(callback).privacyChanged(anyList())
- verify(otherCallback).privacyChanged(anyList())
- }
-
- @Test
- fun testRemoveCallback() {
- doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
- val otherCallback = mock(PrivacyItemController.Callback::class.java)
- privacyItemController.addCallback(callback)
- privacyItemController.addCallback(otherCallback)
- testableLooper.processAllMessages()
- reset(callback)
- reset(otherCallback)
-
- verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback))
- privacyItemController.removeCallback(callback)
- argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true)
- testableLooper.processAllMessages()
- verify(callback, never()).privacyChanged(anyList())
- verify(otherCallback).privacyChanged(anyList())
- }
-
- @Test
- fun testListShouldNotHaveNull() {
- doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0),
- AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
- .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
-
- verify(callback).privacyChanged(capture(argCaptor))
- assertEquals(1, argCaptor.value.size)
- assertThat(argCaptor.value, not(hasItem(nullValue())))
- }
-
- @Test
- fun testListShouldBeCopy() {
- val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA,
- PrivacyApplication("", TEST_UID, mContext)))
- privacyItemController.privacyList = list
- val privacyList = privacyItemController.privacyList
- assertEquals(list, privacyList)
- assertTrue(list !== privacyList)
- }
-
- @Test
- fun testNotListeningWhenIndicatorsDisabled() {
- privacyItemController.devicePropertyChangedListener.onPropertyChanged(
- DeviceConfig.NAMESPACE_PRIVACY,
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED,
- "false")
- privacyItemController.addCallback(callback)
- testableLooper.processAllMessages()
- verify(appOpsController, never()).addCallback(eq(PrivacyItemController.OPS),
- any(AppOpsController.Callback::class.java))
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 06acc73..78970d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -646,7 +646,7 @@
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
- mNotificationInfo.closeControls(mNotificationInfo);
+ mNotificationInfo.closeControls(mNotificationInfo, true);
verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
index df41a84..4f844f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
@@ -131,7 +131,7 @@
));
// Ensure the callback runs at least once
- mWrapper.mUpdatePlaybackUi.run();
+ mWrapper.mOnUpdateTimerTick.run();
verify(mMetricsLogger).write(argThat(logMaker ->
logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index fae853c..7bc2e6d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1946,8 +1946,6 @@
r.binding.service.app.hasClientActivities()
|| r.binding.service.app.treatLikeActivity, null);
}
- mAm.updateOomAdjLocked(r.binding.service.app, false,
- OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
}
}
@@ -2906,15 +2904,15 @@
// Tell the service that it has been unbound.
if (r.app != null && r.app.thread != null) {
- for (int i=r.bindings.size()-1; i>=0; i--) {
+ boolean needOomAdj = false;
+ for (int i = r.bindings.size() - 1; i >= 0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr
+ ": hasBound=" + ibr.hasBound);
if (ibr.hasBound) {
try {
bumpServiceExecutingLocked(r, false, "bring down unbind");
- mAm.updateOomAdjLocked(r.app, true,
- OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
+ needOomAdj = true;
ibr.hasBound = false;
ibr.requested = false;
r.app.thread.scheduleUnbindService(r,
@@ -2926,6 +2924,10 @@
}
}
}
+ if (needOomAdj) {
+ mAm.updateOomAdjLocked(r.app, true,
+ OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
+ }
}
// Check to see if the service had been started as foreground, but being
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index fcd6a0a..884ecba 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -569,9 +569,8 @@
return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
}
- //###
// must be called synchronized on mConnectedDevices
- /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
+ /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
new BtHelper.BluetoothA2dpDeviceInfo(btDevice));
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 99b97cb..a9a8ef2 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -146,6 +146,7 @@
}
}
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
@AudioService.BtProfileConnectionState int state) {
final BluetoothDevice btDevice = btInfo.getBtDevice();
@@ -259,6 +260,7 @@
}
}
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void onBluetoothA2dpActiveDeviceChange(
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
final BluetoothDevice btDevice = btInfo.getBtDevice();
@@ -532,6 +534,7 @@
return mCurAudioRoutes;
}
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void setBluetoothA2dpDeviceConnectionState(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
@@ -559,9 +562,13 @@
final BtHelper.BluetoothA2dpDeviceInfo a2dpDeviceInfo =
new BtHelper.BluetoothA2dpDeviceInfo(device, a2dpVolume, a2dpCodec);
if (profile == BluetoothProfile.A2DP) {
- mDeviceBroker.postA2dpSinkConnection(state,
- a2dpDeviceInfo,
- delay);
+ if (delay == 0) {
+ onSetA2dpSinkConnectionState(a2dpDeviceInfo, state);
+ } else {
+ mDeviceBroker.postA2dpSinkConnection(state,
+ a2dpDeviceInfo,
+ delay);
+ }
} else { //profile == BluetoothProfile.A2DP_SINK
mDeviceBroker.postA2dpSourceConnection(state,
a2dpDeviceInfo,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 30035c8..376e9b5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1275,8 +1275,6 @@
System.VOLUME_SETTINGS_INT[a11yStreamAlias];
mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
mStreamStates[a11yStreamAlias], caller);
- mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
- mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
}
}
if (sIndependentA11yVolume) {
@@ -1577,20 +1575,19 @@
}
private int rescaleIndex(int index, int srcStream, int dstStream) {
- int max = mStreamStates[srcStream].getMaxIndex();
- if (max == 0) {
- Log.e(TAG, "rescaleIndex : Max index should not be zero");
- return mStreamStates[srcStream].getMinIndex();
- }
- final int rescaled =
- (index * mStreamStates[dstStream].getMaxIndex()
- + mStreamStates[srcStream].getMaxIndex() / 2)
- / mStreamStates[srcStream].getMaxIndex();
- if (rescaled < mStreamStates[dstStream].getMinIndex()) {
+ int srcRange =
+ mStreamStates[srcStream].getMaxIndex() - mStreamStates[srcStream].getMinIndex();
+ int dstRange =
+ mStreamStates[dstStream].getMaxIndex() - mStreamStates[dstStream].getMinIndex();
+
+ if (srcRange == 0) {
+ Log.e(TAG, "rescaleIndex : index range should not be zero");
return mStreamStates[dstStream].getMinIndex();
- } else {
- return rescaled;
}
+
+ return mStreamStates[dstStream].getMinIndex()
+ + ((index - mStreamStates[srcStream].getMinIndex()) * dstRange + srcRange / 2)
+ / srcRange;
}
///////////////////////////////////////////////////////////////////////////
@@ -4730,24 +4727,6 @@
}
/**
- * Updates the min/max index values from another stream. Use this when changing the alias
- * for the current stream type.
- * @param sourceStreamType
- */
- // must be sync'd on mSettingsLock before VolumeStreamState.class
- @GuardedBy("VolumeStreamState.class")
- public void refreshRange(int sourceStreamType) {
- mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
- mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
- // verify all current volumes are within bounds
- for (int i = 0 ; i < mIndexMap.size(); i++) {
- final int device = mIndexMap.keyAt(i);
- final int index = mIndexMap.valueAt(i);
- mIndexMap.put(device, getValidIndex(index));
- }
- }
-
- /**
* Copies all device/index pairs from the given VolumeStreamState after initializing
* them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
* has the same stream type as this instance.
@@ -5508,6 +5487,8 @@
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
// address is not used for now, but may be used when multiple a2dp devices are supported
+ sVolumeLogger.log(new AudioEventLogger.StringEvent("avrcpSupportsAbsoluteVolume addr="
+ + address + " support=" + support));
mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 934c7bf..1a63f8f 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -200,16 +200,20 @@
/*package*/ synchronized void setAvrcpAbsoluteVolumeSupported(boolean supported) {
mAvrcpAbsVolSupported = supported;
+ Log.i(TAG, "setAvrcpAbsoluteVolumeSupported supported=" + supported);
}
/*package*/ synchronized void setAvrcpAbsoluteVolumeIndex(int index) {
if (mA2dp == null) {
if (AudioService.DEBUG_VOL) {
- Log.d(TAG, "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp");
+ AudioService.sVolumeLogger.log(new AudioEventLogger.StringEvent(
+ "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp").printLog(TAG));
return;
}
}
if (!mAvrcpAbsVolSupported) {
+ AudioService.sVolumeLogger.log(new AudioEventLogger.StringEvent(
+ "setAvrcpAbsoluteVolumeIndex: abs vol not supported ").printLog(TAG));
return;
}
if (AudioService.DEBUG_VOL) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 1c0ac16..7b45a1b 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -78,7 +78,7 @@
private static final String TAG_CHANNEL = "channel";
private static final String TAG_GROUP = "channelGroup";
private static final String TAG_DELEGATE = "delegate";
- private static final String TAG_STATUS_ICONS = "status_icons";
+ private static final String TAG_STATUS_ICONS = "silent_status_icons";
private static final String ATT_VERSION = "version";
private static final String ATT_NAME = "name";
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a116237..1c775bd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15565,6 +15565,22 @@
@Override
void handleReturnCode() {
if (mVerificationCompleted && mEnableRollbackCompleted) {
+ if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
+ String packageName = "";
+ try {
+ PackageLite packageInfo =
+ new PackageParser().parsePackageLite(origin.file, 0);
+ packageName = packageInfo.packageName;
+ } catch (PackageParserException e) {
+ Slog.e(TAG, "Can't parse package at " + origin.file.getAbsolutePath(), e);
+ }
+ try {
+ observer.onPackageInstalled(packageName, mRet, "Dry run", new Bundle());
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Observer no longer exists.");
+ }
+ return;
+ }
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
mRet = mArgs.copyApk();
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 950450c..9c87c74 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -57,6 +57,7 @@
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -201,10 +202,6 @@
private void preRebootVerification(@NonNull PackageInstallerSession session) {
boolean success = true;
- // STOPSHIP: TODO(b/123753157): Verify APKs through Package Verifier.
- // TODO: Decide whether we want to fail fast by detecting signature mismatches for APKs,
- // right away.
-
final ApexInfoList apexInfoList = new ApexInfoList();
// APEX checks. For single-package sessions, check if they contain an APEX. For
// multi-package sessions, find all the child sessions that contain an APEX.
@@ -230,6 +227,16 @@
return;
}
+ if (sessionContainsApk(session)) {
+ if (!installApksInSession(session, /* preReboot */ true)) {
+ session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "APK verification failed. Check logcat messages for "
+ + "more information.");
+ // TODO(b/118865310): abort the session on apexd.
+ return;
+ }
+ }
+
if (apexInfoList.apexInfos != null && apexInfoList.apexInfos.length > 0) {
// For APEXes, we validate the signature here before we mark the session as ready,
// so we fail the session early if there is a signature mismatch. For APKs, the
@@ -275,21 +282,31 @@
}
}
- private boolean sessionContainsApex(@NonNull PackageInstallerSession session) {
+
+ private boolean sessionContains(@NonNull PackageInstallerSession session,
+ Predicate<PackageInstallerSession> filter) {
if (!session.isMultiPackage()) {
- return isApexSession(session);
+ return filter.test(session);
}
synchronized (mStagedSessions) {
return !(Arrays.stream(session.getChildSessionIds())
// Retrieve cached sessions matching ids.
.mapToObj(i -> mStagedSessions.get(i))
// Filter only the ones containing APEX.
- .filter(childSession -> isApexSession(childSession))
+ .filter(childSession -> filter.test(childSession))
.collect(Collectors.toList())
.isEmpty());
}
}
+ private boolean sessionContainsApex(@NonNull PackageInstallerSession session) {
+ return sessionContains(session, (s) -> isApexSession(s));
+ }
+
+ private boolean sessionContainsApk(@NonNull PackageInstallerSession session) {
+ return sessionContains(session, (s) -> !isApexSession(s));
+ }
+
private void resumeSession(@NonNull PackageInstallerSession session) {
boolean hasApex = sessionContainsApex(session);
if (hasApex) {
@@ -326,7 +343,7 @@
}
}
// The APEX part of the session is activated, proceed with the installation of APKs.
- if (!installApksInSession(session)) {
+ if (!installApksInSession(session, /* preReboot */ false)) {
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Staged installation of APKs failed. Check logcat messages for"
+ "more information.");
@@ -343,7 +360,6 @@
+ "to the previous state of APEXd.");
mPowerManager.reboot(null);
}
-
return;
}
@@ -366,7 +382,7 @@
}
private PackageInstallerSession createAndWriteApkSession(
- @NonNull PackageInstallerSession originalSession) {
+ @NonNull PackageInstallerSession originalSession, boolean preReboot) {
if (originalSession.stageDir == null) {
Slog.wtf(TAG, "Attempting to install a staged APK session with no staging dir");
return null;
@@ -379,9 +395,14 @@
PackageInstaller.SessionParams params = originalSession.params.copy();
params.isStaged = false;
- params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
params.installFlags |= PackageManager.INSTALL_STAGED;
// TODO(b/129744602): use the userid from the original session.
+ if (preReboot) {
+ params.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ params.installFlags |= PackageManager.INSTALL_DRY_RUN;
+ } else {
+ params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
+ }
int apkSessionId = mPi.createSession(
params, originalSession.getInstallerPackageName(),
0 /* UserHandle.SYSTEM */);
@@ -408,17 +429,19 @@
}
private boolean commitApkSession(@NonNull PackageInstallerSession apkSession,
- int originalSessionId) {
+ int originalSessionId, boolean preReboot) {
- if ((apkSession.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
- // If rollback is available for this session, notify the rollback
- // manager of the apk session so it can properly enable rollback.
- final IRollbackManager rm = IRollbackManager.Stub.asInterface(
- ServiceManager.getService(Context.ROLLBACK_SERVICE));
- try {
- rm.notifyStagedApkSession(originalSessionId, apkSession.sessionId);
- } catch (RemoteException re) {
- // Cannot happen, the rollback manager is in the same process.
+ if (!preReboot) {
+ if ((apkSession.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
+ // If rollback is available for this session, notify the rollback
+ // manager of the apk session so it can properly enable rollback.
+ final IRollbackManager rm = IRollbackManager.Stub.asInterface(
+ ServiceManager.getService(Context.ROLLBACK_SERVICE));
+ try {
+ rm.notifyStagedApkSession(originalSessionId, apkSession.sessionId);
+ } catch (RemoteException re) {
+ // Cannot happen, the rollback manager is in the same process.
+ }
}
}
@@ -435,14 +458,15 @@
return false;
}
- private boolean installApksInSession(@NonNull PackageInstallerSession session) {
+ private boolean installApksInSession(@NonNull PackageInstallerSession session,
+ boolean preReboot) {
if (!session.isMultiPackage() && !isApexSession(session)) {
// APK single-packaged staged session. Do a regular install.
- PackageInstallerSession apkSession = createAndWriteApkSession(session);
+ PackageInstallerSession apkSession = createAndWriteApkSession(session, preReboot);
if (apkSession == null) {
return false;
}
- return commitApkSession(apkSession, session.sessionId);
+ return commitApkSession(apkSession, session.sessionId, preReboot);
} else if (session.isMultiPackage()) {
// For multi-package staged sessions containing APKs, we identify which child sessions
// contain an APK, and with those then create a new multi-package group of sessions,
@@ -464,6 +488,9 @@
}
PackageInstaller.SessionParams params = session.params.copy();
params.isStaged = false;
+ if (preReboot) {
+ params.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ }
// TODO(b/129744602): use the userid from the original session.
int apkParentSessionId = mPi.createSession(
params, session.getInstallerPackageName(),
@@ -478,7 +505,8 @@
}
for (PackageInstallerSession sessionToClone : childSessions) {
- PackageInstallerSession apkChildSession = createAndWriteApkSession(sessionToClone);
+ PackageInstallerSession apkChildSession =
+ createAndWriteApkSession(sessionToClone, preReboot);
if (apkChildSession == null) {
return false;
}
@@ -489,7 +517,7 @@
return false;
}
}
- return commitApkSession(apkParentSession, session.sessionId);
+ return commitApkSession(apkParentSession, session.sessionId, preReboot);
}
// APEX single-package staged session, nothing to do.
return true;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 267fbf0..81dd868 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1173,6 +1173,14 @@
}
}
+ if (hardRestricted
+ && (flags & FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
+ // Applying a hard restriction implies revoking it. This might
+ // lead to a system-fixed, revoked permission.
+ flags &= ~FLAG_PERMISSION_SYSTEM_FIXED;
+ wasChanged = true;
+ }
+
if (wasChanged) {
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index b10b5ac..63439d5 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -489,8 +489,7 @@
// Add in all the apps for every user/profile.
for (UserInfo profile : users) {
List<PackageInfo> pi =
- pm.getInstalledPackagesAsUser(
- PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_APEX,
+ pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES,
profile.id);
for (int j = 0; j < pi.size(); j++) {
if (pi.get(j).applicationInfo != null) {
@@ -2513,7 +2512,7 @@
@Override
public void onBootPhase(int phase) {
super.onBootPhase(phase);
- if (phase == PHASE_BOOT_COMPLETED) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
mStatsCompanionService.systemReady();
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 765c9d0..b97ecec 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5867,8 +5867,10 @@
*/
Intent getSecondaryHomeIntent(String preferredPackage) {
final Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
- if (preferredPackage == null) {
- // Using the component stored in config if no package name.
+ final boolean useSystemProvidedLauncher = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary);
+ if (preferredPackage == null || useSystemProvidedLauncher) {
+ // Using the component stored in config if no package name or forced.
final String secondaryHomeComponent = mContext.getResources().getString(
com.android.internal.R.string.config_secondaryHomeComponent);
intent.setComponent(ComponentName.unflattenFromString(secondaryHomeComponent));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 0f7b35c..c77e25f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -30,6 +30,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
@@ -54,6 +55,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
@@ -601,6 +603,73 @@
}
/**
+ * Tests that the default secondary home activity is always picked when it is in forced by
+ * config_useSystemProvidedLauncherForSecondary.
+ */
+ @Test
+ public void testResolveSecondaryHomeActivityForced() throws Exception {
+ Resources resources = mContext.getResources();
+ spyOn(resources);
+ try {
+ // setUp: set secondary launcher and force it.
+ final String defaultSecondaryHome =
+ "com.android.test/com.android.test.TestDefaultSecondaryHome";
+ final ComponentName secondaryComp = ComponentName.unflattenFromString(
+ defaultSecondaryHome);
+ doReturn(defaultSecondaryHome).when(resources).getString(
+ com.android.internal.R.string.config_secondaryHomeComponent);
+ doReturn(true).when(resources).getBoolean(
+ com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary);
+ final Intent secondaryHomeIntent = mService.getSecondaryHomeIntent(null);
+ assertEquals(secondaryComp, secondaryHomeIntent.getComponent());
+ final ActivityInfo aInfoSecondary = new ActivityInfo();
+ aInfoSecondary.name = secondaryComp.getClassName();
+ aInfoSecondary.applicationInfo = new ApplicationInfo();
+ aInfoSecondary.applicationInfo.packageName = secondaryComp.getPackageName();
+ doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ refEq(secondaryHomeIntent));
+ final Intent homeIntent = mService.getHomeIntent();
+ final ActivityInfo aInfoDefault = new ActivityInfo();
+ aInfoDefault.name = "fakeHomeActivity";
+ aInfoDefault.applicationInfo = new ApplicationInfo();
+ aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
+ doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ refEq(homeIntent));
+ // Let resolveActivities call to validate both main launcher and second launcher so that
+ // resolveActivities call does not work as enabler for secondary.
+ final List<ResolveInfo> resolutions1 = new ArrayList<>();
+ final ResolveInfo resolveInfo1 = new ResolveInfo();
+ resolveInfo1.activityInfo = new ActivityInfo();
+ resolveInfo1.activityInfo.name = aInfoDefault.name;
+ resolveInfo1.activityInfo.applicationInfo = aInfoDefault.applicationInfo;
+ resolutions1.add(resolveInfo1);
+ doReturn(resolutions1).when(mRootActivityContainer).resolveActivities(anyInt(),
+ refEq(homeIntent));
+ final List<ResolveInfo> resolutions2 = new ArrayList<>();
+ final ResolveInfo resolveInfo2 = new ResolveInfo();
+ resolveInfo2.activityInfo = new ActivityInfo();
+ resolveInfo2.activityInfo.name = aInfoSecondary.name;
+ resolveInfo2.activityInfo.applicationInfo = aInfoSecondary.applicationInfo;
+ resolutions2.add(resolveInfo2);
+ doReturn(resolutions2).when(mRootActivityContainer).resolveActivities(anyInt(),
+ refEq(secondaryHomeIntent));
+ doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ any(), anyInt(), anyBoolean());
+
+ // Run the test
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ .resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
+ assertEquals(secondaryComp.getClassName(), resolvedInfo.first.name);
+ assertEquals(secondaryComp.getPackageName(),
+ resolvedInfo.first.applicationInfo.packageName);
+ assertEquals(aInfoSecondary.name, resolvedInfo.first.name);
+ } finally {
+ // tearDown
+ reset(resources);
+ }
+ }
+
+ /**
* Tests that secondary home should be selected if default home not support secondary displays
* or there is no matched activity in the same package as selected default home.
*/
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 6000b56..cd5fd97 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -95,6 +95,10 @@
private Bundle mExtras;
private Set<String> mPreviousExtraKeys;
private final Object mExtrasLock = new Object();
+ private Uri mAddress;
+ private int mAddressPresentation;
+ private String mCallerDisplayName;
+ private int mCallerDisplayNamePresentation;
private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
@Override
@@ -987,12 +991,67 @@
*/
public final void setAddress(Uri address, int presentation) {
Log.d(this, "setAddress %s", address);
+ mAddress = address;
+ mAddressPresentation = presentation;
for (Listener l : mListeners) {
l.onAddressChanged(this, address, presentation);
}
}
/**
+ * Returns the "address" associated with the conference. This is applicable in two cases:
+ * <ol>
+ * <li>When {@link #setConferenceState(boolean)} is used to mark a conference as
+ * temporarily "not a conference"; we need to present the correct address in the in-call
+ * UI.</li>
+ * <li>When the conference is not hosted on the current device, we need to know the address
+ * information for the purpose of showing the original address to the user, as well as for
+ * logging to the call log.</li>
+ * </ol>
+ * @return The address of the conference, or {@code null} if not applicable.
+ * @hide
+ */
+ public final Uri getAddress() {
+ return mAddress;
+ }
+
+ /**
+ * Returns the address presentation associated with the conference.
+ * <p>
+ * This is applicable in two cases:
+ * <ol>
+ * <li>When {@link #setConferenceState(boolean)} is used to mark a conference as
+ * temporarily "not a conference"; we need to present the correct address in the in-call
+ * UI.</li>
+ * <li>When the conference is not hosted on the current device, we need to know the address
+ * information for the purpose of showing the original address to the user, as well as for
+ * logging to the call log.</li>
+ * </ol>
+ * @return The address of the conference, or {@code null} if not applicable.
+ * @hide
+ */
+ public final int getAddressPresentation() {
+ return mAddressPresentation;
+ }
+
+ /**
+ * @return The caller display name (CNAP).
+ * @hide
+ */
+ public final String getCallerDisplayName() {
+ return mCallerDisplayName;
+ }
+
+ /**
+ * @return The presentation requirements for the handle.
+ * See {@link TelecomManager} for valid values.
+ * @hide
+ */
+ public final int getCallerDisplayNamePresentation() {
+ return mCallerDisplayNamePresentation;
+ }
+
+ /**
* Sets the caller display name (CNAP) of this {@link Conference}. Used when
* {@link #setConferenceState(boolean)} is called to mark a conference temporarily as NOT a
* conference.
@@ -1004,6 +1063,8 @@
*/
public final void setCallerDisplayName(String callerDisplayName, int presentation) {
Log.d(this, "setCallerDisplayName %s", callerDisplayName);
+ mCallerDisplayName = callerDisplayName;
+ mCallerDisplayNamePresentation = presentation;
for (Listener l : mListeners) {
l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 28e6596..47587c5 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -424,8 +424,16 @@
*/
public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1 << 10;
+ /**
+ * Set by the framework to indicate that a Conference or Connection is hosted by a device other
+ * than the current one. Used in scenarios where the conference originator is the remote device
+ * and the current device is a participant of that conference.
+ * @hide
+ */
+ public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
+
//**********************************************************************************************
- // Next PROPERTY value: 1<<10
+ // Next PROPERTY value: 1<<12
//**********************************************************************************************
/**
@@ -850,6 +858,10 @@
builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall");
}
+ if (can(properties, PROPERTY_REMOTELY_HOSTED)) {
+ builder.append(isLong ? " PROPERTY_REMOTELY_HOSTED" : " remote_hst");
+ }
+
builder.append("]");
return builder.toString();
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index c66e92b..626fcc4 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2056,7 +2056,11 @@
conference.getConnectTimeMillis(),
conference.getConnectionStartElapsedRealTime(),
conference.getStatusHints(),
- conference.getExtras());
+ conference.getExtras(),
+ conference.getAddress(),
+ conference.getAddressPresentation(),
+ conference.getCallerDisplayName(),
+ conference.getCallerDisplayNamePresentation());
mAdapter.addConferenceCall(id, parcelableConference);
mAdapter.setVideoProvider(id, conference.getVideoProvider());
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index 636e4b2..ede0594 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -16,6 +16,7 @@
package android.telecom;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -42,6 +43,10 @@
private StatusHints mStatusHints;
private Bundle mExtras;
private long mConnectElapsedTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
+ private final Uri mAddress;
+ private final int mAddressPresentation;
+ private final String mCallerDisplayName;
+ private final int mCallerDisplayNamePresentation;
public ParcelableConference(
PhoneAccountHandle phoneAccount,
@@ -54,7 +59,11 @@
long connectTimeMillis,
long connectElapsedTimeMillis,
StatusHints statusHints,
- Bundle extras) {
+ Bundle extras,
+ Uri address,
+ int addressPresentation,
+ String callerDisplayName,
+ int callerDisplayNamePresentation) {
mPhoneAccount = phoneAccount;
mState = state;
mConnectionCapabilities = connectionCapabilities;
@@ -66,6 +75,10 @@
mStatusHints = statusHints;
mExtras = extras;
mConnectElapsedTimeMillis = connectElapsedTimeMillis;
+ mAddress = address;
+ mAddressPresentation = addressPresentation;
+ mCallerDisplayName = callerDisplayName;
+ mCallerDisplayNamePresentation = callerDisplayNamePresentation;
}
@Override
@@ -134,6 +147,14 @@
return mExtras;
}
+ public Uri getHandle() {
+ return mAddress;
+ }
+
+ public int getHandlePresentation() {
+ return mAddressPresentation;
+ }
+
public static final @android.annotation.NonNull Parcelable.Creator<ParcelableConference> CREATOR =
new Parcelable.Creator<ParcelableConference> () {
@Override
@@ -152,10 +173,15 @@
Bundle extras = source.readBundle(classLoader);
int properties = source.readInt();
long connectElapsedTimeMillis = source.readLong();
+ Uri address = source.readParcelable(classLoader);
+ int addressPresentation = source.readInt();
+ String callerDisplayName = source.readString();
+ int callerDisplayNamePresentation = source.readInt();
return new ParcelableConference(phoneAccount, state, capabilities, properties,
connectionIds, videoCallProvider, videoState, connectTimeMillis,
- connectElapsedTimeMillis, statusHints, extras);
+ connectElapsedTimeMillis, statusHints, extras, address, addressPresentation,
+ callerDisplayName, callerDisplayNamePresentation);
}
@Override
@@ -185,5 +211,9 @@
destination.writeBundle(mExtras);
destination.writeInt(mConnectionProperties);
destination.writeLong(mConnectElapsedTimeMillis);
+ destination.writeParcelable(mAddress, 0);
+ destination.writeInt(mAddressPresentation);
+ destination.writeString(mCallerDisplayName);
+ destination.writeInt(mCallerDisplayNamePresentation);
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a125e31..8ef381d 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1132,6 +1132,7 @@
* <li> 8: Wi-Fi</li>
* <li> 9: WiFi Calling</li>
* <li> 10: VoWifi</li>
+ * <li> 11: %s WiFi Calling</li>
* @hide
*/
public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index addd9e0..65db458 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -302,11 +302,27 @@
* subscription.
*
* Default value is 0.
+ *
+ * @deprecated Replaced by {@link #DATA_ENABLED_OVERRIDE_RULES}
+ * @hide
*/
- /** @hide */
+ @Deprecated
public static final String WHITE_LISTED_APN_DATA = "white_listed_apn_data";
/**
+ * TelephonyProvider column name data_enabled_override_rules.
+ * It's a list of rules for overriding data enabled settings. The syntax is
+ * For example, "mms=nonDefault" indicates enabling data for mms in non-default subscription.
+ * "default=nonDefault&inVoiceCall" indicates enabling data for internet in non-default
+ * subscription and while is in voice call.
+ *
+ * Default value is empty string.
+ *
+ * @hide
+ */
+ public static final String DATA_ENABLED_OVERRIDE_RULES = "data_enabled_override_rules";
+
+ /**
* This constant is to designate a subscription as a Local-SIM Subscription.
* <p> A Local-SIM can be a physical SIM inserted into a sim-slot in the device, or eSIM on the
* device.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2ba34c6..d6011b9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -105,6 +105,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.regex.Matcher;
@@ -9239,6 +9240,10 @@
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
+ } catch (NullPointerException e) {
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
+ "getServiceStateForSubscriber " + subId + " NPE");
}
return null;
}
@@ -11141,4 +11146,52 @@
}
return true;
}
+
+ /**
+ * Set allowing mobile data during voice call.
+ *
+ * @param allow {@code true} if allowing using data during voice call, {@code false} if
+ * disallowed
+ *
+ * @return {@code false} if the setting is changed.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setDataAllowedDuringVoiceCall(boolean allow) {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.setDataAllowedDuringVoiceCall(getSubId(), allow);
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check whether data is allowed during voice call. Note this is for dual sim device that
+ * data might be disabled on non-default data subscription but explicitly turned on by settings.
+ *
+ * @return {@code true} if data is allowed during voice call.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public boolean isDataAllowedInVoiceCall() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.isDataAllowedInVoiceCall(getSubId());
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ return false;
+ }
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a78bae4..165be64 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1310,6 +1310,9 @@
* @hide
*/
public static String getApnTypeString(int apnType) {
+ if (apnType == TYPE_ALL) {
+ return "*";
+ }
String apnTypeString = APN_TYPE_INT_MAP.get(apnType);
return apnTypeString == null ? "Unknown" : apnTypeString;
}
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index bb5c251..cde6db4 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -94,7 +94,7 @@
public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48;
public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50;
- public static final int EVENT_APN_WHITE_LIST_CHANGE = BASE + 51;
+ public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51;
/***** Constants *****/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index cf1323a..5a27a0f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1619,7 +1619,7 @@
* <p>
* See {@link UiccCardInfo} for more details on the kind of information available.
*
- * @param callingPackage package making the call, used to evaluate carrier privileges
+ * @param callingPackage package making the call, used to evaluate carrier privileges
* @return a list of UiccCardInfo objects, representing information on the currently inserted
* UICCs and eUICCs. Each UiccCardInfo in the list will have private information filtered out if
* the caller does not have adequate permissions for that card.
@@ -1996,4 +1996,15 @@
* Returns the MMS user agent profile URL.
*/
String getMmsUAProfUrl(int subId);
+
+ /**
+ * Set allowing mobile data during voice call.
+ */
+ boolean setDataAllowedDuringVoiceCall(int subId, boolean allow);
+
+ /**
+ * Check whether data is allowed during voice call. Note this is for dual sim device that
+ * data might be disabled on non-default data subscription but explicitly turned on by settings.
+ */
+ boolean isDataAllowedInVoiceCall(int subId);
}