Merge "Fix duplicate reg. KeyguardSliceViewController in DumpManager."
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
index 050fecd..d3938f4 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
@@ -17,7 +17,6 @@
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.view.Display;
@@ -136,4 +135,22 @@
}
}
}
+
+ @Test
+ public void getDisplayMetrics() {
+ ResourcesManager resourcesManager = ResourcesManager.getInstance();
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ // Invalidate cache.
+ resourcesManager.applyConfigurationToResourcesLocked(
+ resourcesManager.getConfiguration(), null);
+ state.resumeTiming();
+
+ // Invoke twice for testing cache.
+ resourcesManager.getDisplayMetrics();
+ resourcesManager.getDisplayMetrics();
+ }
+ }
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 9b684f1..693402a 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -652,7 +652,7 @@
(unsigned long)mCurrentSlicedBucket.size());
if (verbose) {
for (const auto& it : mCurrentSlicedBucket) {
- for (const auto& interval : it.second) {
+ for (const auto& interval : it.second.intervals) {
fprintf(out, "\t(what)%s\t(states)%s (value)%s\n",
it.first.getDimensionKeyInWhat().toString().c_str(),
it.first.getStateValuesKey().toString().c_str(),
@@ -804,7 +804,8 @@
// We need to get the intervals stored with the previous state key so we can
// close these value intervals.
const auto oldStateKey = baseInfos[0].currentState;
- vector<Interval>& intervals = mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)];
+ vector<Interval>& intervals =
+ mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)].intervals;
if (intervals.size() < mFieldMatchers.size()) {
VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
intervals.resize(mFieldMatchers.size());
@@ -990,7 +991,7 @@
bool bucketHasData = false;
// The current bucket is large enough to keep.
for (const auto& slice : mCurrentSlicedBucket) {
- ValueBucket bucket = buildPartialBucket(bucketEndTime, slice.second);
+ PastValueBucket bucket = buildPartialBucket(bucketEndTime, slice.second.intervals);
bucket.mConditionTrueNs = conditionTrueDuration;
// it will auto create new vector of ValuebucketInfo if the key is not found.
if (bucket.valueIndex.size() > 0) {
@@ -1030,9 +1031,9 @@
mCurrentBucketNum += numBucketsForward;
}
-ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
- const std::vector<Interval>& intervals) {
- ValueBucket bucket;
+PastValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
+ const std::vector<Interval>& intervals) {
+ PastValueBucket bucket;
bucket.mBucketStartNs = mCurrentBucketStartTimeNs;
bucket.mBucketEndNs = bucketEndTime;
for (const auto& interval : intervals) {
@@ -1059,7 +1060,7 @@
// Cleanup data structure to aggregate values.
for (auto it = mCurrentSlicedBucket.begin(); it != mCurrentSlicedBucket.end();) {
bool obsolete = true;
- for (auto& interval : it->second) {
+ for (auto& interval : it->second.intervals) {
interval.hasValue = false;
interval.sampleSize = 0;
if (interval.seenNewData) {
@@ -1107,7 +1108,7 @@
continue;
}
// TODO: fix this when anomaly can accept double values
- auto& interval = slice.second[0];
+ auto& interval = slice.second.intervals[0];
if (interval.hasValue) {
mCurrentFullBucket[slice.first] += interval.value.long_value;
}
@@ -1126,7 +1127,7 @@
for (auto& tracker : mAnomalyTrackers) {
if (tracker != nullptr) {
// TODO: fix this when anomaly can accept double values
- auto& interval = slice.second[0];
+ auto& interval = slice.second.intervals[0];
if (interval.hasValue) {
tracker->addPastBucket(slice.first, interval.value.long_value,
mCurrentBucketNum);
@@ -1139,7 +1140,7 @@
// Accumulate partial bucket.
for (const auto& slice : mCurrentSlicedBucket) {
// TODO: fix this when anomaly can accept double values
- auto& interval = slice.second[0];
+ auto& interval = slice.second.intervals[0];
if (interval.hasValue) {
mCurrentFullBucket[slice.first] += interval.value.long_value;
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index e72002e..fffc866 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -31,7 +31,7 @@
namespace os {
namespace statsd {
-struct ValueBucket {
+struct PastValueBucket {
int64_t mBucketStartNs;
int64_t mBucketEndNs;
std::vector<int> valueIndex;
@@ -41,7 +41,6 @@
int64_t mConditionTrueNs;
};
-
// Aggregates values within buckets.
//
// There are different events that might complete a bucket
@@ -173,7 +172,7 @@
// if this is pulled metric
const bool mIsPulled;
- // internal state of an ongoing aggregation bucket.
+ // Tracks the value information of one value field.
typedef struct {
// Index in multi value aggregation.
int valueIndex;
@@ -188,6 +187,12 @@
bool seenNewData = false;
} Interval;
+ // Internal state of an ongoing aggregation bucket.
+ typedef struct CurrentValueBucket {
+ // Value information for each value field of the metric.
+ std::vector<Interval> intervals;
+ } CurrentValueBucket;
+
typedef struct {
// Holds current base value of the dimension. Take diff and update if necessary.
Value base;
@@ -199,14 +204,16 @@
bool hasCurrentState;
} BaseInfo;
- std::unordered_map<MetricDimensionKey, std::vector<Interval>> mCurrentSlicedBucket;
+ // Tracks the internal state in the ongoing aggregation bucket for each DimensionsInWhat
+ // key and StateValuesKey pair.
+ std::unordered_map<MetricDimensionKey, CurrentValueBucket> mCurrentSlicedBucket;
std::unordered_map<HashableDimensionKey, std::vector<BaseInfo>> mCurrentBaseInfo;
std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
// Save the past buckets and we can clear when the StatsLogReport is dumped.
- std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>> mPastBuckets;
+ std::unordered_map<MetricDimensionKey, std::vector<PastValueBucket>> mPastBuckets;
const int64_t mMinBucketSizeNs;
@@ -224,8 +231,8 @@
void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
int64_t originalPullTimeNs, int64_t eventElapsedTimeNs);
- ValueBucket buildPartialBucket(int64_t bucketEndTime,
- const std::vector<Interval>& intervals);
+ PastValueBucket buildPartialBucket(int64_t bucketEndTime,
+ const std::vector<Interval>& intervals);
void initCurrentSlicedBucket(int64_t nextBucketStartTimeNs);
@@ -234,7 +241,7 @@
// Reset diff base and mHasGlobalBase
void resetBase();
- static const size_t kBucketSize = sizeof(ValueBucket{});
+ static const size_t kBucketSize = sizeof(PastValueBucket{});
const size_t mDimensionSoftLimit;
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 1000aea..ec8adfd 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -57,7 +57,7 @@
double epsilon = 0.001;
static void assertPastBucketValuesSingleKey(
- const std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>>& mPastBuckets,
+ const std::unordered_map<MetricDimensionKey, std::vector<PastValueBucket>>& mPastBuckets,
const std::initializer_list<int>& expectedValuesList,
const std::initializer_list<int64_t>& expectedDurationNsList,
const std::initializer_list<int64_t>& expectedStartTimeNsList,
@@ -79,7 +79,7 @@
ASSERT_EQ(1, mPastBuckets.size());
ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
- const vector<ValueBucket>& buckets = mPastBuckets.begin()->second;
+ const vector<PastValueBucket>& buckets = mPastBuckets.begin()->second;
for (int i = 0; i < expectedValues.size(); i++) {
EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
<< "Values differ at index " << i;
@@ -288,7 +288,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -304,7 +304,7 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -322,7 +322,7 @@
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -426,7 +426,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -455,7 +455,7 @@
allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// the base was reset
@@ -489,7 +489,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -502,7 +502,7 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
@@ -516,7 +516,7 @@
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(36, curBaseInfo.base.long_value);
@@ -549,7 +549,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -562,7 +562,7 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
@@ -573,7 +573,7 @@
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(36, curBaseInfo.base.long_value);
@@ -624,7 +624,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -641,7 +641,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(110, curBaseInfo.base.long_value);
@@ -654,7 +654,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
@@ -879,7 +879,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -888,7 +888,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(30, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -925,8 +925,8 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(20, curInterval.value.long_value);
LogEvent event3(/*uid=*/0, /*pid=*/0);
@@ -935,7 +935,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(50, curInterval.value.long_value);
valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
@@ -946,7 +946,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(50, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1089,7 +1089,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:true sum:0 start:11
@@ -1104,7 +1104,7 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// tartUpdated:false sum:12
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1121,7 +1121,7 @@
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:12
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1180,7 +1180,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
@@ -1189,7 +1189,7 @@
// pull on bucket boundary come late, condition change happens before it
valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
@@ -1203,7 +1203,7 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1252,7 +1252,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1265,7 +1265,7 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1274,7 +1274,7 @@
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(130, curBaseInfo.base.long_value);
@@ -1286,7 +1286,7 @@
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(140, curBaseInfo.base.long_value);
@@ -1327,7 +1327,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1335,7 +1335,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1364,7 +1364,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1374,7 +1374,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(20, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1405,7 +1405,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval;
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(1, curInterval.sampleSize);
@@ -1414,7 +1414,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(25, curInterval.value.long_value);
EXPECT_EQ(2, curInterval.sampleSize);
@@ -1449,7 +1449,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1457,7 +1457,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(25, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1487,7 +1487,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
@@ -1499,7 +1499,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(5, curInterval.value.long_value);
@@ -1509,7 +1509,7 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
@@ -1520,7 +1520,7 @@
CreateRepeatedValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 15);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
@@ -1558,7 +1558,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
@@ -1572,11 +1572,11 @@
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(5, curInterval.value.long_value);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(2, curInterval.value.long_value);
@@ -1587,13 +1587,13 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(25, curBaseInfo.base.long_value);
@@ -1604,12 +1604,12 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(29, curBaseInfo.base.long_value);
@@ -1656,7 +1656,7 @@
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
+ auto& interval1 = iter->second.intervals[0];
auto iterBase = valueProducer->mCurrentBaseInfo.begin();
auto& baseInfo1 = iterBase->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -1692,7 +1692,7 @@
}
EXPECT_TRUE(it != iter);
EXPECT_TRUE(itBase != iterBase);
- auto& interval2 = it->second[0];
+ auto& interval2 = it->second.intervals[0];
auto& baseInfo2 = itBase->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
@@ -1732,7 +1732,7 @@
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
const auto& it = valueProducer->mCurrentSlicedBucket.begin();
- ValueMetricProducer::Interval& interval1 = it->second[0];
+ ValueMetricProducer::Interval& interval1 = it->second.intervals[0];
ValueMetricProducer::BaseInfo& baseInfo1 =
valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -1761,7 +1761,7 @@
}
}
EXPECT_TRUE(it2 != it);
- ValueMetricProducer::Interval& interval2 = it2->second[0];
+ ValueMetricProducer::Interval& interval2 = it2->second.intervals[0];
ValueMetricProducer::BaseInfo& baseInfo2 =
valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -1792,10 +1792,10 @@
// Get new references now that entries have been deleted from the map
const auto& it3 = valueProducer->mCurrentSlicedBucket.begin();
const auto& it4 = std::next(valueProducer->mCurrentSlicedBucket.begin());
- ASSERT_EQ(it3->second.size(), 1);
- ASSERT_EQ(it4->second.size(), 1);
- ValueMetricProducer::Interval& interval3 = it3->second[0];
- ValueMetricProducer::Interval& interval4 = it4->second[0];
+ ASSERT_EQ(it3->second.intervals.size(), 1);
+ ASSERT_EQ(it4->second.intervals.size(), 1);
+ ValueMetricProducer::Interval& interval3 = it3->second.intervals[0];
+ ValueMetricProducer::Interval& interval4 = it4->second.intervals[0];
ValueMetricProducer::BaseInfo& baseInfo3 =
valueProducer->mCurrentBaseInfo.find(it3->first.getDimensionKeyInWhat())->second[0];
ValueMetricProducer::BaseInfo& baseInfo4 =
@@ -1837,7 +1837,7 @@
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
+ auto& interval1 = iter->second.intervals[0];
auto iterBase = valueProducer->mCurrentBaseInfo.begin();
auto& baseInfo1 = iterBase->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -1875,7 +1875,7 @@
}
EXPECT_TRUE(it != iter);
EXPECT_TRUE(itBase != iterBase);
- auto interval2 = it->second[0];
+ auto interval2 = it->second.intervals[0];
auto baseInfo2 = itBase->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
@@ -1889,7 +1889,7 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
// Only one interval left. One was trimmed.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
@@ -1903,7 +1903,7 @@
allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 14));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
- interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, baseInfo2.hasBase);
EXPECT_EQ(14, baseInfo2.base.long_value);
@@ -1943,7 +1943,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
@@ -1980,7 +1980,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
@@ -2030,7 +2030,7 @@
valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2103,7 +2103,7 @@
valueProducer->mHasGlobalBase = true;
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
@@ -2156,7 +2156,7 @@
// Contains base from last pull which was successful.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(140, curBaseInfo.base.long_value);
@@ -2294,7 +2294,7 @@
// Contains base from last pull which was successful.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(140, curBaseInfo.base.long_value);
@@ -2373,7 +2373,7 @@
// Last pull failed so base has been reset.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2460,7 +2460,7 @@
valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2469,7 +2469,7 @@
// Empty pull.
valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2513,7 +2513,7 @@
valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
@@ -2524,7 +2524,7 @@
allData.clear();
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// Data is empty, base should be reset.
EXPECT_EQ(false, curBaseInfo.hasBase);
@@ -2572,12 +2572,12 @@
auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
- EXPECT_EQ(false, iterator->second[0].hasValue);
+ EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
iterator++;
baseInfoIter++;
EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
- EXPECT_EQ(false, iterator->second[0].hasValue);
+ EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
@@ -2676,7 +2676,7 @@
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(5, curBaseInfo.base.long_value);
@@ -2811,7 +2811,7 @@
valueProducer->onConditionChanged(false, bucketStartTimeNs + 12);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(2, curInterval.value.long_value);
@@ -3045,7 +3045,7 @@
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
@@ -3058,7 +3058,7 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -3091,7 +3091,7 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -3995,7 +3995,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after screen state change kStateUnknown->ON.
auto screenEvent = CreateScreenStateChangedEvent(
@@ -4016,8 +4016,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change ON->OFF.
screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
@@ -4037,16 +4037,16 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, kStateUnknown}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change OFF->ON.
screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
@@ -4067,24 +4067,24 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(12, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(12, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, ON}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, kStateUnknown}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Start dump report and check output.
ProtoOutputStream output;
@@ -4206,7 +4206,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after screen state change kStateUnknown->ON.
auto screenEvent = CreateScreenStateChangedEvent(
@@ -4227,8 +4227,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change ON->VR.
// Both ON and VR are in the same state group, so the base should not change.
@@ -4250,8 +4250,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change VR->ON.
// Both ON and VR are in the same state group, so the base should not change.
@@ -4273,8 +4273,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change VR->OFF.
screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
@@ -4295,16 +4295,16 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(screenOnGroup.group_id(),
it->first.getStateValuesKey().getValues()[0].mValue.long_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(16, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(16, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, kStateUnknown}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Start dump report and check output.
ProtoOutputStream output;
@@ -4459,7 +4459,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 2}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -4475,7 +4475,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 1 process state change kStateUnknown -> Foreground.
auto uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4497,8 +4497,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Base for dimension key {uid 2}
it++;
@@ -4514,7 +4514,7 @@
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 2 process state change kStateUnknown -> Background.
uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4535,8 +4535,8 @@
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Base for dimension key {uid 2}
it++;
@@ -4552,8 +4552,8 @@
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Pull at end of first bucket.
vector<shared_ptr<LogEvent>> allData;
@@ -4582,7 +4582,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 1}
it++;
@@ -4599,7 +4599,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 1, FOREGROUND}
it++;
@@ -4608,7 +4608,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 2, kStateUnknown}
it++;
@@ -4617,7 +4617,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 1 process state change from Foreground -> Background.
uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4642,7 +4642,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 1}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -4658,7 +4658,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 1, FOREGROUND}
it++;
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
@@ -4666,8 +4666,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Value for key {uid 2, kStateUnknown}
it++;
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
@@ -4675,7 +4675,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 1 process state change Background->Foreground.
uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4699,7 +4699,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 1}
it++;
@@ -4716,7 +4716,7 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 1, BACKGROUND}
it++;
@@ -4725,8 +4725,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Value for key {uid 1, FOREGROUND}
it++;
@@ -4735,8 +4735,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Value for key {uid 2, kStateUnknown}
it++;
@@ -4867,13 +4867,13 @@
itBase->second[0].currentState.getValues()[0].mValue.int_value);
// Value for key {{}, -1}
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- std::unordered_map<MetricDimensionKey, std::vector<ValueMetricProducer::Interval>>::iterator
- it = valueProducer->mCurrentSlicedBucket.begin();
+ std::unordered_map<MetricDimensionKey, ValueMetricProducer::CurrentValueBucket>::iterator it =
+ valueProducer->mCurrentSlicedBucket.begin();
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after battery saver mode OFF event.
unique_ptr<LogEvent> batterySaverOffEvent =
@@ -4895,8 +4895,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::ON,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Pull at end of first bucket.
vector<shared_ptr<LogEvent>> allData;
@@ -4933,8 +4933,8 @@
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::OFF,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Start dump report and check output.
ProtoOutputStream output;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 7cd3fca..9e4ab33 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -54,6 +54,7 @@
import java.io.PrintWriter;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
@@ -245,7 +246,7 @@
/**
* A cache of DisplayId, DisplayAdjustments to Display.
*/
- private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>>
+ private final ArrayMap<Pair<Integer, DisplayAdjustments>, SoftReference<Display>>
mAdjustedDisplays = new ArrayMap<>();
/**
@@ -373,25 +374,28 @@
? new DisplayAdjustments(displayAdjustments) : new DisplayAdjustments();
final Pair<Integer, DisplayAdjustments> key =
Pair.create(displayId, displayAdjustmentsCopy);
+ SoftReference<Display> sd;
synchronized (this) {
- WeakReference<Display> wd = mAdjustedDisplays.get(key);
- if (wd != null) {
- final Display display = wd.get();
- if (display != null) {
- return display;
- }
- }
- final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
- if (dm == null) {
- // may be null early in system startup
- return null;
- }
- final Display display = dm.getCompatibleDisplay(displayId, key.second);
- if (display != null) {
- mAdjustedDisplays.put(key, new WeakReference<>(display));
- }
- return display;
+ sd = mAdjustedDisplays.get(key);
}
+ if (sd != null) {
+ final Display display = sd.get();
+ if (display != null) {
+ return display;
+ }
+ }
+ final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+ if (dm == null) {
+ // may be null early in system startup
+ return null;
+ }
+ final Display display = dm.getCompatibleDisplay(displayId, key.second);
+ if (display != null) {
+ synchronized (this) {
+ mAdjustedDisplays.put(key, new SoftReference<>(display));
+ }
+ }
+ return display;
}
/**
diff --git a/libs/WindowManager/Shell/res/layout/pip_menu_activity.xml b/libs/WindowManager/Shell/res/layout/pip_menu.xml
similarity index 100%
rename from libs/WindowManager/Shell/res/layout/pip_menu_activity.xml
rename to libs/WindowManager/Shell/res/layout/pip_menu.xml
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
index fd6685f..6d31a8d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
@@ -22,8 +22,6 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.pip.phone.PipMenuActivity;
-import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
import com.android.systemui.wm.DisplaySystemBarsController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
@@ -43,12 +41,4 @@
return new DisplaySystemBarsController(context, wmService, displayController,
mainHandler, transactionPool);
}
-
- /** TODO(b/150319024): PipMenuActivity will move to a Window */
- @SysUISingleton
- @PipMenuActivityClass
- @Provides
- Class<?> providePipMenuActivityClass() {
- return PipMenuActivity.class;
- }
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index af008b9..7f4f580 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -530,20 +530,6 @@
androidprv:alwaysFocusable="true"
android:excludeFromRecents="true" />
- <activity
- android:name=".pip.phone.PipMenuActivity"
- android:permission="com.android.systemui.permission.SELF"
- android:theme="@style/PipPhoneOverlayControlTheme"
- android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
- android:excludeFromRecents="true"
- android:exported="false"
- android:resizeableActivity="true"
- android:supportsPictureInPicture="true"
- android:stateNotNeeded="true"
- android:taskAffinity=""
- android:launchMode="singleTop"
- androidprv:alwaysFocusable="true" />
-
<!-- started from SliceProvider -->
<activity android:name=".SlicePermissionActivity"
android:theme="@style/Theme.SystemUI.Dialog.Alert"
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 7421ec1..c956702 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -49,6 +49,9 @@
import android.util.Log;
import android.util.Size;
import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowManager;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -57,6 +60,7 @@
import com.android.internal.os.SomeArgs;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.pip.phone.PipMenuActivityController;
import com.android.systemui.pip.phone.PipUpdateThread;
import com.android.systemui.stackdivider.SplitScreen;
import com.android.wm.shell.R;
@@ -95,6 +99,7 @@
private static final int MSG_FINISH_RESIZE = 4;
private static final int MSG_RESIZE_USER = 5;
+ private final Context mContext;
private final Handler mMainHandler;
private final Handler mUpdateHandler;
private final PipBoundsHandler mPipBoundsHandler;
@@ -107,6 +112,8 @@
private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
private final Optional<SplitScreen> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
+ private SurfaceControlViewHost mPipViewHost;
+ private SurfaceControl mPipMenuSurface;
// These callbacks are called on the update thread
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
@@ -212,6 +219,7 @@
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer) {
+ mContext = context;
mMainHandler = new Handler(Looper.getMainLooper());
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
mPipBoundsHandler = boundsHandler;
@@ -504,6 +512,45 @@
}
/**
+ * Setup the ViewHost and attach the provided menu view to the ViewHost.
+ */
+ public void attachPipMenuViewHost(View menuView, WindowManager.LayoutParams lp) {
+ if (mPipMenuSurface != null) {
+ Log.e(TAG, "PIP Menu View already created and attached.");
+ return;
+ }
+
+ if (Looper.getMainLooper() != Looper.myLooper()) {
+ throw new RuntimeException("PipMenuView needs to be attached on the main thread.");
+ }
+
+ mPipViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(),
+ (android.os.Binder) null);
+ mPipMenuSurface = mPipViewHost.getSurfacePackage().getSurfaceControl();
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.reparent(mPipMenuSurface, mLeash);
+ transaction.show(mPipMenuSurface);
+ transaction.setRelativeLayer(mPipMenuSurface, mLeash, 1);
+ transaction.apply();
+ mPipViewHost.setView(menuView, lp);
+ }
+
+
+ /**
+ * Releases the PIP Menu's View host, remove it from PIP task surface.
+ */
+ public void detachPipMenuViewHost() {
+ if (mPipMenuSurface != null) {
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.remove(mPipMenuSurface);
+ transaction.apply();
+ mPipMenuSurface = null;
+ mPipViewHost = null;
+ }
+ }
+
+
+ /**
* Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
* Meanwhile this callback is invoked whenever the task is removed. For instance:
* - as a result of removeStacksInWindowingModes from WM
@@ -838,6 +885,12 @@
WindowContainerTransaction wct = new WindowContainerTransaction();
prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);
applyFinishBoundsResize(wct, direction);
+ runOnMainHandler(() -> {
+ if (mPipViewHost != null) {
+ mPipViewHost.relayout(PipMenuActivityController.getPipMenuLayoutParams(
+ destinationBounds.width(), destinationBounds.height()));
+ }
+ });
}
private void prepareFinishResizeTransaction(Rect destinationBounds,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index d8864ec..5ef5b90 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -49,7 +49,6 @@
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
-import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
@@ -267,7 +266,6 @@
@Inject
public PipManager(Context context, BroadcastDispatcher broadcastDispatcher,
- @PipMenuActivityClass Class<?> pipMenuActivityClass,
ConfigurationController configController,
DeviceConfigProxy deviceConfig,
DisplayController displayController,
@@ -296,8 +294,8 @@
mPipTaskOrganizer.registerPipTransitionCallback(this);
mInputConsumerController = InputConsumerController.getPipInputConsumer();
mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
- mMenuController = new PipMenuActivityController(context, pipMenuActivityClass,
- mMediaController, mInputConsumerController);
+ mMenuController = new PipMenuActivityController(context,
+ mMediaController, mInputConsumerController, mPipTaskOrganizer);
mTouchHandler = new PipTouchHandler(context, mActivityManager,
mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer,
floatingContentCoordinator, deviceConfig, sysUiState, pipUiEventLogger);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
deleted file mode 100644
index 1b1b2de..0000000
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.pip.phone;
-
-import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
-import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
-import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
-
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU_WITH_DELAY;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_RESIZE_HANDLE;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
-import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
-import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
-import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.PendingIntent.CanceledException;
-import android.app.RemoteAction;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ParceledListSlice;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.Pair;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager.LayoutParams;
-import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-
-import com.android.systemui.Interpolators;
-import com.android.wm.shell.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Translucent activity that gets started on top of a task in PIP to allow the user to control it.
- * TODO(b/150319024): PipMenuActivity will move to a Window
- */
-public class PipMenuActivity extends Activity {
-
- private static final String TAG = "PipMenuActivity";
-
- private static final int MESSAGE_INVALID_TYPE = -1;
-
- public static final int MESSAGE_SHOW_MENU = 1;
- public static final int MESSAGE_POKE_MENU = 2;
- public static final int MESSAGE_HIDE_MENU = 3;
- public static final int MESSAGE_UPDATE_ACTIONS = 4;
- public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
- public static final int MESSAGE_ANIMATION_ENDED = 6;
- public static final int MESSAGE_POINTER_EVENT = 7;
- public static final int MESSAGE_MENU_EXPANDED = 8;
- public static final int MESSAGE_FADE_OUT_MENU = 9;
- public static final int MESSAGE_UPDATE_MENU_LAYOUT = 10;
-
- private static final int INITIAL_DISMISS_DELAY = 3500;
- private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
- private static final long MENU_FADE_DURATION = 125;
- private static final long MENU_SLOW_FADE_DURATION = 175;
- private static final long MENU_SHOW_ON_EXPAND_START_DELAY = 30;
-
- private static final float MENU_BACKGROUND_ALPHA = 0.3f;
- private static final float DISMISS_BACKGROUND_ALPHA = 0.6f;
-
- private static final float DISABLED_ACTION_ALPHA = 0.54f;
-
- private static final boolean ENABLE_RESIZE_HANDLE = false;
-
- private int mMenuState;
- private boolean mResize = true;
- private boolean mAllowMenuTimeout = true;
- private boolean mAllowTouches = true;
-
- private final List<RemoteAction> mActions = new ArrayList<>();
-
- private AccessibilityManager mAccessibilityManager;
- private Drawable mBackgroundDrawable;
- private View mMenuContainer;
- private LinearLayout mActionsGroup;
- private int mBetweenActionPaddingLand;
-
- private AnimatorSet mMenuContainerAnimator;
-
- private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
- new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final float alpha = (float) animation.getAnimatedValue();
- mBackgroundDrawable.setAlpha((int) (MENU_BACKGROUND_ALPHA*alpha*255));
- }
- };
-
- private Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_SHOW_MENU: {
- final Bundle data = (Bundle) msg.obj;
- showMenu(data.getInt(EXTRA_MENU_STATE),
- data.getParcelable(EXTRA_STACK_BOUNDS),
- data.getBoolean(EXTRA_ALLOW_TIMEOUT),
- data.getBoolean(EXTRA_WILL_RESIZE_MENU),
- data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY),
- data.getBoolean(EXTRA_SHOW_RESIZE_HANDLE));
- break;
- }
- case MESSAGE_POKE_MENU:
- cancelDelayedFinish();
- break;
- case MESSAGE_HIDE_MENU:
- hideMenu((Runnable) msg.obj);
- break;
- case MESSAGE_UPDATE_ACTIONS: {
- final Bundle data = (Bundle) msg.obj;
- final ParceledListSlice<RemoteAction> actions = data.getParcelable(
- EXTRA_ACTIONS);
- setActions(data.getParcelable(EXTRA_STACK_BOUNDS), actions != null
- ? actions.getList() : Collections.emptyList());
- break;
- }
- case MESSAGE_UPDATE_DISMISS_FRACTION: {
- final Bundle data = (Bundle) msg.obj;
- updateDismissFraction(data.getFloat(EXTRA_DISMISS_FRACTION));
- break;
- }
- case MESSAGE_ANIMATION_ENDED: {
- mAllowTouches = true;
- break;
- }
- case MESSAGE_POINTER_EVENT: {
- final MotionEvent ev = (MotionEvent) msg.obj;
- dispatchPointerEvent(ev);
- break;
- }
- case MESSAGE_MENU_EXPANDED : {
- if (mMenuContainerAnimator == null) {
- return;
- }
- mMenuContainerAnimator.setStartDelay(MENU_SHOW_ON_EXPAND_START_DELAY);
- mMenuContainerAnimator.start();
- break;
- }
- case MESSAGE_FADE_OUT_MENU: {
- fadeOutMenu();
- break;
- }
- case MESSAGE_UPDATE_MENU_LAYOUT: {
- if (mPipMenuIconsAlgorithm == null) {
- return;
- }
- final Rect bounds = (Rect) msg.obj;
- mPipMenuIconsAlgorithm.onBoundsChanged(bounds);
- break;
- }
- }
- }
- };
- private Messenger mToControllerMessenger;
- private Messenger mMessenger = new Messenger(mHandler);
-
- private final Runnable mFinishRunnable = this::hideMenu;
-
- protected View mViewRoot;
- protected View mSettingsButton;
- protected View mDismissButton;
- protected View mResizeHandle;
- protected View mTopEndContainer;
- protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- // Set the flags to allow us to watch for outside touches and also hide the menu and start
- // manipulating the PIP in the same touch gesture
- getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
-
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.pip_menu_activity);
-
- mAccessibilityManager = getSystemService(AccessibilityManager.class);
- mBackgroundDrawable = new ColorDrawable(Color.BLACK);
- mBackgroundDrawable.setAlpha(0);
- mViewRoot = findViewById(R.id.background);
- mViewRoot.setBackground(mBackgroundDrawable);
- mMenuContainer = findViewById(R.id.menu_container);
- mMenuContainer.setAlpha(0);
- mTopEndContainer = findViewById(R.id.top_end_container);
- mSettingsButton = findViewById(R.id.settings);
- mSettingsButton.setAlpha(0);
- mSettingsButton.setOnClickListener((v) -> {
- if (v.getAlpha() != 0) {
- showSettings();
- }
- });
- mDismissButton = findViewById(R.id.dismiss);
- mDismissButton.setAlpha(0);
- mDismissButton.setOnClickListener(v -> dismissPip());
- findViewById(R.id.expand_button).setOnClickListener(v -> {
- if (mMenuContainer.getAlpha() != 0) {
- expandPip();
- }
- });
- mResizeHandle = findViewById(R.id.resize_handle);
- mResizeHandle.setAlpha(0);
- mActionsGroup = findViewById(R.id.actions_group);
- mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
- R.dimen.pip_between_action_padding_land);
- mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(this.getApplicationContext());
- mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer,
- mResizeHandle, mSettingsButton, mDismissButton);
- updateFromIntent(getIntent());
- setTitle(R.string.pip_menu_title);
- setDisablePreviewScreenshots(true);
-
- // Hide without an animation.
- getWindow().setExitTransition(null);
-
- initAccessibility();
- }
-
- private void initAccessibility() {
- getWindow().getDecorView().setAccessibilityDelegate(new View.AccessibilityDelegate() {
- @Override
- public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- String label = getResources().getString(R.string.pip_menu_title);
- info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, label));
- }
-
- @Override
- public boolean performAccessibilityAction(View host, int action, Bundle args) {
- if (action == ACTION_CLICK && mMenuState == MENU_STATE_CLOSE) {
- Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_SHOW_MENU;
- sendMessage(m, "Could not notify controller to show PIP menu");
- }
- return super.performAccessibilityAction(host, action, args);
- }
- });
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
- hideMenu();
- return true;
- }
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- updateFromIntent(intent);
- }
-
- @Override
- public void onUserInteraction() {
- if (mAllowMenuTimeout) {
- repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
- }
- }
-
- @Override
- protected void onUserLeaveHint() {
- super.onUserLeaveHint();
-
- // If another task is starting on top of the menu, then hide and finish it so that it can be
- // recreated on the top next time it starts
- hideMenu();
- }
-
- @Override
- public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
- super.onTopResumedActivityChanged(isTopResumedActivity);
- if (!isTopResumedActivity && mMenuState != MENU_STATE_NONE) {
- hideMenu();
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- // In cases such as device lock, hide and finish it so that it can be recreated on the top
- // next time it starts, see also {@link #onUserLeaveHint}
- hideMenu();
- cancelDelayedFinish();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- // Fallback, if we are destroyed for any other reason (like when the task is being reset),
- // also reset the callback.
- notifyActivityCallback(null);
- }
-
- @Override
- public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
- if (!isInPictureInPictureMode) {
- finish();
- }
- }
-
- /**
- * Dispatch a pointer event from {@link PipTouchHandler}.
- */
- private void dispatchPointerEvent(MotionEvent event) {
- if (event.isTouchEvent()) {
- dispatchTouchEvent(event);
- } else {
- dispatchGenericMotionEvent(event);
- }
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (!mAllowTouches) {
- return false;
- }
-
- // On the first action outside the window, hide the menu
- switch (ev.getAction()) {
- case MotionEvent.ACTION_OUTSIDE:
- hideMenu();
- return true;
- }
- return super.dispatchTouchEvent(ev);
- }
-
- @Override
- public void finish() {
- notifyActivityCallback(null);
- super.finish();
- }
-
- @Override
- public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
- // Do nothing
- }
-
- private void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
- boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
- mAllowMenuTimeout = allowMenuTimeout;
- if (mMenuState != menuState) {
- // Disallow touches if the menu needs to resize while showing, and we are transitioning
- // to/from a full menu state.
- boolean disallowTouchesUntilAnimationEnd = resizeMenuOnShow &&
- (mMenuState == MENU_STATE_FULL || menuState == MENU_STATE_FULL);
- mAllowTouches = !disallowTouchesUntilAnimationEnd;
- cancelDelayedFinish();
- updateActionViews(stackBounds);
- if (mMenuContainerAnimator != null) {
- mMenuContainerAnimator.cancel();
- }
- mMenuContainerAnimator = new AnimatorSet();
- ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
- mMenuContainer.getAlpha(), 1f);
- menuAnim.addUpdateListener(mMenuBgUpdateListener);
- ObjectAnimator settingsAnim = ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA,
- mSettingsButton.getAlpha(), 1f);
- ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
- mDismissButton.getAlpha(), 1f);
- ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
- mResizeHandle.getAlpha(),
- ENABLE_RESIZE_HANDLE && menuState == MENU_STATE_CLOSE && showResizeHandle
- ? 1f : 0f);
- if (menuState == MENU_STATE_FULL) {
- mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
- resizeAnim);
- } else {
- mMenuContainerAnimator.playTogether(dismissAnim, resizeAnim);
- }
- mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
- mMenuContainerAnimator.setDuration(menuState == MENU_STATE_CLOSE
- ? MENU_FADE_DURATION
- : MENU_SLOW_FADE_DURATION);
- if (allowMenuTimeout) {
- mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- repostDelayedFinish(INITIAL_DISMISS_DELAY);
- }
- });
- }
- if (withDelay) {
- // starts the menu container animation after window expansion is completed
- notifyMenuStateChange(menuState, resizeMenuOnShow, MESSAGE_MENU_EXPANDED);
- } else {
- notifyMenuStateChange(menuState, resizeMenuOnShow, MESSAGE_INVALID_TYPE);
- mMenuContainerAnimator.start();
- }
- } else {
- // If we are already visible, then just start the delayed dismiss and unregister any
- // existing input consumers from the previous drag
- if (allowMenuTimeout) {
- repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
- }
- }
- }
-
- /**
- * Different from {@link #hideMenu()}, this function does not try to finish this menu activity
- * and instead, it fades out the controls by setting the alpha to 0 directly without menu
- * visibility callbacks invoked.
- */
- private void fadeOutMenu() {
- mMenuContainer.setAlpha(0f);
- mSettingsButton.setAlpha(0f);
- mDismissButton.setAlpha(0f);
- mResizeHandle.setAlpha(0f);
- }
-
- private void hideMenu() {
- hideMenu(null);
- }
-
- private void hideMenu(Runnable animationEndCallback) {
- hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false /* isDismissing */,
- true /* animate */);
- }
-
- private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
- boolean isDismissing, boolean animate) {
- if (mMenuState != MENU_STATE_NONE) {
- cancelDelayedFinish();
- if (notifyMenuVisibility) {
- notifyMenuStateChange(MENU_STATE_NONE, mResize, MESSAGE_INVALID_TYPE);
- }
- mMenuContainerAnimator = new AnimatorSet();
- ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
- mMenuContainer.getAlpha(), 0f);
- menuAnim.addUpdateListener(mMenuBgUpdateListener);
- ObjectAnimator settingsAnim = ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA,
- mSettingsButton.getAlpha(), 0f);
- ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
- mDismissButton.getAlpha(), 0f);
- ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
- mResizeHandle.getAlpha(), 0f);
- mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim);
- mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
- mMenuContainerAnimator.setDuration(animate ? MENU_FADE_DURATION : 0);
- mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (animationFinishedRunnable != null) {
- animationFinishedRunnable.run();
- }
-
- if (!isDismissing) {
- // If we are dismissing the PiP, then don't try to pre-emptively finish the
- // menu activity
- finish();
- }
- }
- });
- mMenuContainerAnimator.start();
- } else {
- // If the menu is not visible, just finish now
- finish();
- }
- }
-
- private void updateFromIntent(Intent intent) {
- mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
- if (mToControllerMessenger == null) {
- Log.w(TAG, "Controller messenger is null. Stopping.");
- finish();
- return;
- }
- notifyActivityCallback(mMessenger);
-
- ParceledListSlice<RemoteAction> actions = intent.getParcelableExtra(EXTRA_ACTIONS);
- if (actions != null) {
- mActions.clear();
- mActions.addAll(actions.getList());
- }
-
- final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE);
- if (menuState != MENU_STATE_NONE) {
- Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS);
- boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true);
- boolean willResizeMenu = intent.getBooleanExtra(EXTRA_WILL_RESIZE_MENU, false);
- boolean withDelay = intent.getBooleanExtra(EXTRA_SHOW_MENU_WITH_DELAY, false);
- boolean showResizeHandle = intent.getBooleanExtra(EXTRA_SHOW_RESIZE_HANDLE, false);
- showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
- showResizeHandle);
- }
- }
-
- private void setActions(Rect stackBounds, List<RemoteAction> actions) {
- mActions.clear();
- mActions.addAll(actions);
- updateActionViews(stackBounds);
- }
-
- private void updateActionViews(Rect stackBounds) {
- ViewGroup expandContainer = findViewById(R.id.expand_container);
- ViewGroup actionsContainer = findViewById(R.id.actions_container);
- actionsContainer.setOnTouchListener((v, ev) -> {
- // Do nothing, prevent click through to parent
- return true;
- });
-
- if (mActions.isEmpty() || mMenuState == MENU_STATE_CLOSE) {
- actionsContainer.setVisibility(View.INVISIBLE);
- } else {
- actionsContainer.setVisibility(View.VISIBLE);
- if (mActionsGroup != null) {
- // Ensure we have as many buttons as actions
- final LayoutInflater inflater = LayoutInflater.from(this);
- while (mActionsGroup.getChildCount() < mActions.size()) {
- final ImageButton actionView = (ImageButton) inflater.inflate(
- R.layout.pip_menu_action, mActionsGroup, false);
- mActionsGroup.addView(actionView);
- }
-
- // Update the visibility of all views
- for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
- mActionsGroup.getChildAt(i).setVisibility(i < mActions.size()
- ? View.VISIBLE
- : View.GONE);
- }
-
- // Recreate the layout
- final boolean isLandscapePip = stackBounds != null &&
- (stackBounds.width() > stackBounds.height());
- for (int i = 0; i < mActions.size(); i++) {
- final RemoteAction action = mActions.get(i);
- final ImageButton actionView = (ImageButton) mActionsGroup.getChildAt(i);
-
- // TODO: Check if the action drawable has changed before we reload it
- action.getIcon().loadDrawableAsync(this, d -> {
- d.setTint(Color.WHITE);
- actionView.setImageDrawable(d);
- }, mHandler);
- actionView.setContentDescription(action.getContentDescription());
- if (action.isEnabled()) {
- actionView.setOnClickListener(v -> {
- mHandler.post(() -> {
- try {
- action.getActionIntent().send();
- } catch (CanceledException e) {
- Log.w(TAG, "Failed to send action", e);
- }
- });
- });
- }
- actionView.setEnabled(action.isEnabled());
- actionView.setAlpha(action.isEnabled() ? 1f : DISABLED_ACTION_ALPHA);
-
- // Update the margin between actions
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
- actionView.getLayoutParams();
- lp.leftMargin = (isLandscapePip && i > 0) ? mBetweenActionPaddingLand : 0;
- }
- }
-
- // Update the expand container margin to adjust the center of the expand button to
- // account for the existence of the action container
- FrameLayout.LayoutParams expandedLp =
- (FrameLayout.LayoutParams) expandContainer.getLayoutParams();
- expandedLp.topMargin = getResources().getDimensionPixelSize(
- R.dimen.pip_action_padding);
- expandedLp.bottomMargin = getResources().getDimensionPixelSize(
- R.dimen.pip_expand_container_edge_margin);
- expandContainer.requestLayout();
- }
- }
-
- private void updateDismissFraction(float fraction) {
- int alpha;
- final float menuAlpha = 1 - fraction;
- if (mMenuState == MENU_STATE_FULL) {
- mMenuContainer.setAlpha(menuAlpha);
- mSettingsButton.setAlpha(menuAlpha);
- mDismissButton.setAlpha(menuAlpha);
- final float interpolatedAlpha =
- MENU_BACKGROUND_ALPHA * menuAlpha + DISMISS_BACKGROUND_ALPHA * fraction;
- alpha = (int) (interpolatedAlpha * 255);
- } else {
- if (mMenuState == MENU_STATE_CLOSE) {
- mDismissButton.setAlpha(menuAlpha);
- }
- alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
- }
- mBackgroundDrawable.setAlpha(alpha);
- }
-
- private void notifyMenuStateChange(int menuState, boolean resize, int callbackWhat) {
- mMenuState = menuState;
- mResize = resize;
- Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_MENU_STATE_CHANGED;
- m.arg1 = menuState;
- m.arg2 = resize ? 1 : 0;
- if (callbackWhat != MESSAGE_INVALID_TYPE) {
- // This message could be sent across processes when in secondary user.
- // Make the receiver end sending back via our own Messenger
- m.replyTo = mMessenger;
- final Bundle data = new Bundle(1);
- data.putInt(PipMenuActivityController.EXTRA_MESSAGE_CALLBACK_WHAT, callbackWhat);
- m.obj = data;
- }
- sendMessage(m, "Could not notify controller of PIP menu visibility");
- }
-
- private void expandPip() {
- // Do not notify menu visibility when hiding the menu, the controller will do this when it
- // handles the message
- hideMenu(() -> {
- sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
- "Could not notify controller to expand PIP");
- }, false /* notifyMenuVisibility */, false /* isDismissing */, true /* animate */);
- }
-
- private void dismissPip() {
- // Since tapping on the close-button invokes a double-tap wait callback in PipTouchHandler,
- // we want to disable animating the fadeout animation of the buttons in order to call on
- // PipTouchHandler#onPipDismiss fast enough.
- final boolean animate = mMenuState != MENU_STATE_CLOSE;
- // Do not notify menu visibility when hiding the menu, the controller will do this when it
- // handles the message
- hideMenu(() -> {
- sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
- "Could not notify controller to dismiss PIP");
- }, false /* notifyMenuVisibility */, true /* isDismissing */, animate);
- }
-
- private void showSettings() {
- final Pair<ComponentName, Integer> topPipActivityInfo =
- PipUtils.getTopPipActivity(this, ActivityManager.getService());
- if (topPipActivityInfo.first != null) {
- final UserHandle user = UserHandle.of(topPipActivityInfo.second);
- final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS,
- Uri.fromParts("package", topPipActivityInfo.first.getPackageName(), null));
- settingsIntent.putExtra(Intent.EXTRA_USER_HANDLE, user);
- settingsIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(settingsIntent);
- }
- }
-
- private void notifyActivityCallback(Messenger callback) {
- Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK;
- m.replyTo = callback;
- m.arg1 = mResize ? 1 : 0;
- sendMessage(m, "Could not notify controller of activity finished");
- }
-
- private void sendEmptyMessage(int what, String errorMsg) {
- Message m = Message.obtain();
- m.what = what;
- sendMessage(m, errorMsg);
- }
-
- private void sendMessage(Message m, String errorMsg) {
- if (mToControllerMessenger == null) {
- return;
- }
- try {
- mToControllerMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, errorMsg, e);
- }
- }
-
- private void cancelDelayedFinish() {
- mHandler.removeCallbacks(mFinishRunnable);
- }
-
- private void repostDelayedFinish(int delay) {
- int recommendedTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(delay,
- FLAG_CONTENT_ICONS | FLAG_CONTENT_CONTROLS);
- mHandler.removeCallbacks(mFinishRunnable);
- mHandler.postDelayed(mFinishRunnable, recommendedTimeout);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 383f6b3..873ba26 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -19,27 +19,20 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import android.annotation.Nullable;
import android.app.ActivityManager.StackInfo;
-import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.RemoteAction;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.os.Bundle;
import android.os.Debug;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.WindowManager;
+import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController;
@@ -58,30 +51,10 @@
private static final String TAG = "PipMenuActController";
private static final boolean DEBUG = false;
- public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
- public static final String EXTRA_ACTIONS = "actions";
- public static final String EXTRA_STACK_BOUNDS = "stack_bounds";
- public static final String EXTRA_ALLOW_TIMEOUT = "allow_timeout";
- public static final String EXTRA_WILL_RESIZE_MENU = "resize_menu_on_show";
- public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction";
- public static final String EXTRA_MENU_STATE = "menu_state";
- public static final String EXTRA_SHOW_MENU_WITH_DELAY = "show_menu_with_delay";
- public static final String EXTRA_SHOW_RESIZE_HANDLE = "show_resize_handle";
- public static final String EXTRA_MESSAGE_CALLBACK_WHAT = "message_callback_what";
-
- public static final int MESSAGE_MENU_STATE_CHANGED = 100;
- public static final int MESSAGE_EXPAND_PIP = 101;
- public static final int MESSAGE_DISMISS_PIP = 103;
- public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
- public static final int MESSAGE_SHOW_MENU = 107;
-
public static final int MENU_STATE_NONE = 0;
public static final int MENU_STATE_CLOSE = 1;
public static final int MENU_STATE_FULL = 2;
- // The duration to wait before we consider the start activity as having timed out
- private static final long START_ACTIVITY_REQUEST_TIMEOUT_MS = 300;
-
/**
* A listener interface to receive notification on changes in PIP.
*/
@@ -110,9 +83,8 @@
void onPipShowMenu();
}
- /** TODO(b/150319024): PipMenuActivity will move to a Window */
- private Class<?> mPipMenuActivityClass;
private Context mContext;
+ private PipTaskOrganizer mPipTaskOrganizer;
private PipMediaController mMediaController;
private InputConsumerController mInputConsumerController;
@@ -121,63 +93,7 @@
private ParceledListSlice<RemoteAction> mMediaActions;
private int mMenuState;
- // The dismiss fraction update is sent frequently, so use a temporary bundle for the message
- private Bundle mTmpDismissFractionData = new Bundle();
-
- private Runnable mOnAnimationEndRunnable;
- private boolean mStartActivityRequested;
- private long mStartActivityRequestedTime;
- private Messenger mToActivityMessenger;
- private Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_MENU_STATE_CHANGED: {
- final int menuState = msg.arg1;
- final boolean resize = msg.arg2 != 0;
- onMenuStateChanged(menuState, resize,
- getMenuStateChangeFinishedCallback(msg.replyTo, (Bundle) msg.obj));
- break;
- }
- case MESSAGE_EXPAND_PIP: {
- mListeners.forEach(Listener::onPipExpand);
- break;
- }
- case MESSAGE_DISMISS_PIP: {
- mListeners.forEach(Listener::onPipDismiss);
- break;
- }
- case MESSAGE_SHOW_MENU: {
- mListeners.forEach(Listener::onPipShowMenu);
- break;
- }
- case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
- mToActivityMessenger = msg.replyTo;
- setStartActivityRequested(false);
- if (mOnAnimationEndRunnable != null) {
- mOnAnimationEndRunnable.run();
- mOnAnimationEndRunnable = null;
- }
- // Mark the menu as invisible once the activity finishes as well
- if (mToActivityMessenger == null) {
- final boolean resize = msg.arg1 != 0;
- onMenuStateChanged(MENU_STATE_NONE, resize, null /* callback */);
- }
- break;
- }
- }
- }
- };
- private Messenger mMessenger = new Messenger(mHandler);
-
- private Runnable mStartActivityRequestedTimeoutRunnable = () -> {
- setStartActivityRequested(false);
- if (mOnAnimationEndRunnable != null) {
- mOnAnimationEndRunnable.run();
- mOnAnimationEndRunnable = null;
- }
- Log.e(TAG, "Expected start menu activity request timed out");
- };
+ private PipMenuView mPipMenuView;
private ActionListener mMediaActionListener = new ActionListener() {
@Override
@@ -187,39 +103,40 @@
}
};
- public PipMenuActivityController(Context context, Class<?> pipMenuActivityClass,
- PipMediaController mediaController, InputConsumerController inputConsumerController
+ public PipMenuActivityController(Context context,
+ PipMediaController mediaController, InputConsumerController inputConsumerController,
+ PipTaskOrganizer pipTaskOrganizer
) {
mContext = context;
mMediaController = mediaController;
mInputConsumerController = inputConsumerController;
- mPipMenuActivityClass = pipMenuActivityClass;
+ mPipTaskOrganizer = pipTaskOrganizer;
}
- public boolean isMenuActivityVisible() {
- return mToActivityMessenger != null;
+ public boolean isMenuVisible() {
+ return mPipMenuView != null && mMenuState != MENU_STATE_NONE;
}
public void onActivityPinned() {
+ if (mPipMenuView == null) {
+ WindowManager.LayoutParams lp =
+ getPipMenuLayoutParams(0, 0);
+ mPipMenuView = new PipMenuView(mContext, this);
+ mPipTaskOrganizer.attachPipMenuViewHost(mPipMenuView, lp);
+ }
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
}
public void onActivityUnpinned() {
hideMenu();
mInputConsumerController.unregisterInputConsumer();
- setStartActivityRequested(false);
+ mPipTaskOrganizer.detachPipMenuViewHost();
+ mPipMenuView = null;
}
public void onPinnedStackAnimationEnded() {
- // Note: Only active menu activities care about this event
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_ANIMATION_ENDED;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu pinned animation ended", e);
- }
+ if (isMenuVisible()) {
+ mPipMenuView.onPipAnimationEnded();
}
}
@@ -236,27 +153,13 @@
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
public void setDismissFraction(float fraction) {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
- Log.d(TAG, "setDismissFraction() hasActivity=" + (mToActivityMessenger != null)
+ Log.d(TAG, "setDismissFraction() isMenuVisible=" + isMenuVisible
+ " fraction=" + fraction);
}
- if (mToActivityMessenger != null) {
- mTmpDismissFractionData.clear();
- mTmpDismissFractionData.putFloat(EXTRA_DISMISS_FRACTION, fraction);
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_UPDATE_DISMISS_FRACTION;
- m.obj = mTmpDismissFractionData;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to update dismiss fraction", e);
- }
- } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
- // If we haven't requested the start activity, or if it previously took too long to
- // start, then start it
- startMenuActivity(MENU_STATE_NONE, null /* stackBounds */,
- false /* allowMenuTimeout */, false /* resizeMenuOnShow */,
- false /* withDelay */, false /* showResizeHandle */);
+ if (isMenuVisible) {
+ mPipMenuView.updateDismissFraction(fraction);
}
}
@@ -282,27 +185,11 @@
false /* withDelay */, showResizeHandle);
}
- private Runnable getMenuStateChangeFinishedCallback(@Nullable Messenger replyTo,
- @Nullable Bundle data) {
- if (replyTo == null || data == null) {
- return null;
- }
- return () -> {
- try {
- final Message m = Message.obtain();
- m.what = data.getInt(EXTRA_MESSAGE_CALLBACK_WHAT);
- replyTo.send(m);
- } catch (RemoteException e) {
- // ignored
- }
- };
- }
-
private void showMenuInternal(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
if (DEBUG) {
Log.d(TAG, "showMenu() state=" + menuState
- + " hasActivity=" + (mToActivityMessenger != null)
+ + " isMenuVisible=" + isMenuVisible()
+ " allowMenuTimeout=" + allowMenuTimeout
+ " willResizeMenu=" + willResizeMenu
+ " withDelay=" + withDelay
@@ -310,64 +197,34 @@
+ " callers=\n" + Debug.getCallers(5, " "));
}
- if (mToActivityMessenger != null) {
- Bundle data = new Bundle();
- data.putInt(EXTRA_MENU_STATE, menuState);
- if (stackBounds != null) {
- data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
- }
- data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
- data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
- data.putBoolean(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
- data.putBoolean(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
- m.obj = data;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to show", e);
- }
- } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
- // If we haven't requested the start activity, or if it previously took too long to
- // start, then start it
- startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
- showResizeHandle);
+ if (mPipMenuView == null) {
+ Log.e(TAG, "PipMenu has not been attached yet.");
+ return;
}
+ mPipMenuView.showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
+ showResizeHandle);
}
/**
* Pokes the menu, indicating that the user is interacting with it.
*/
public void pokeMenu() {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
- Log.d(TAG, "pokeMenu() hasActivity=" + (mToActivityMessenger != null));
+ Log.d(TAG, "pokeMenu() isMenuVisible=" + isMenuVisible);
}
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_POKE_MENU;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify poke menu", e);
- }
+ if (isMenuVisible) {
+ mPipMenuView.pokeMenu();
}
}
private void fadeOutMenu() {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
- Log.d(TAG, "fadeOutMenu() state=" + mMenuState
- + " hasActivity=" + (mToActivityMessenger != null)
- + " callers=\n" + Debug.getCallers(5, " "));
+ Log.d(TAG, "fadeOutMenu() isMenuVisible=" + isMenuVisible);
}
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_FADE_OUT_MENU;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to fade out", e);
- }
+ if (isMenuVisible) {
+ mPipMenuView.fadeOutMenu();
}
}
@@ -375,19 +232,14 @@
* Hides the menu activity.
*/
public void hideMenu() {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
Log.d(TAG, "hideMenu() state=" + mMenuState
- + " hasActivity=" + (mToActivityMessenger != null)
+ + " isMenuVisible=" + isMenuVisible
+ " callers=\n" + Debug.getCallers(5, " "));
}
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to hide", e);
- }
+ if (isMenuVisible) {
+ mPipMenuView.hideMenu();
}
}
@@ -395,29 +247,11 @@
* Hides the menu activity.
*/
public void hideMenu(Runnable onStartCallback, Runnable onEndCallback) {
- if (mStartActivityRequested) {
- // If the menu has been start-requested, but not actually started, then we defer the
- // trigger callback until the menu has started and called back to the controller.
- mOnAnimationEndRunnable = onEndCallback;
- onStartCallback.run();
-
- // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
- // callbacks. Don't continue to wait for the menu to show past some timeout.
- mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
- mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
- START_ACTIVITY_REQUEST_TIMEOUT_MS);
- } else if (mMenuState != MENU_STATE_NONE && mToActivityMessenger != null) {
+ if (isMenuVisible()) {
// If the menu is visible in either the closed or full state, then hide the menu and
// trigger the animation trigger afterwards
onStartCallback.run();
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
- m.obj = onEndCallback;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify hide menu", e);
- }
+ mPipMenuView.hideMenu(onEndCallback);
}
}
@@ -438,6 +272,18 @@
updateMenuActions();
}
+ void onPipExpand() {
+ mListeners.forEach(Listener::onPipExpand);
+ }
+
+ void onPipDismiss() {
+ mListeners.forEach(Listener::onPipDismiss);
+ }
+
+ void onPipShowMenu() {
+ mListeners.forEach(Listener::onPipShowMenu);
+ }
+
/**
* @return the best set of actions to show in the PiP menu.
*/
@@ -449,47 +295,20 @@
}
/**
- * Starts the menu activity on the top task of the pinned stack.
+ * Returns a default LayoutParams for the PIP Menu.
+ * @param width the PIP stack width.
+ * @param height the PIP stack height.
*/
- private void startMenuActivity(int menuState, Rect stackBounds, boolean allowMenuTimeout,
- boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
- try {
- StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
- if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
- pinnedStackInfo.taskIds.length > 0) {
- Intent intent = new Intent(mContext, mPipMenuActivityClass);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
- intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
- if (stackBounds != null) {
- intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds);
- }
- intent.putExtra(EXTRA_MENU_STATE, menuState);
- intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
- intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
- intent.putExtra(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
- intent.putExtra(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
- ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
- options.setLaunchTaskId(
- pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
- options.setTaskOverlay(true, true /* canResume */);
- mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
- setStartActivityRequested(true);
- } else {
- Log.e(TAG, "No PIP tasks found");
- }
- } catch (RemoteException e) {
- setStartActivityRequested(false);
- Log.e(TAG, "Error showing PIP menu activity", e);
- }
+ public static WindowManager.LayoutParams getPipMenuLayoutParams(int width, int height) {
+ return new WindowManager.LayoutParams(width, height,
+ WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSLUCENT);
}
/**
- * Updates the PiP menu activity with the best set of actions provided.
+ * Updates the PiP menu with the best set of actions provided.
*/
private void updateMenuActions() {
- if (mToActivityMessenger != null) {
+ if (isMenuVisible()) {
// Fetch the pinned stack bounds
Rect stackBounds = null;
try {
@@ -499,20 +318,10 @@
stackBounds = pinnedStackInfo.bounds;
}
} catch (RemoteException e) {
- Log.e(TAG, "Error showing PIP menu activity", e);
+ Log.e(TAG, "Error showing PIP menu", e);
}
- Bundle data = new Bundle();
- data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
- data.putParcelable(EXTRA_ACTIONS, resolveMenuActions());
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_UPDATE_ACTIONS;
- m.obj = data;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu activity to update actions", e);
- }
+ mPipMenuView.setActions(stackBounds, resolveMenuActions().getList());
}
}
@@ -524,17 +333,9 @@
}
/**
- * @return whether the time of the activity request has exceeded the timeout.
- */
- private boolean isStartActivityRequestedElapsed() {
- return (SystemClock.uptimeMillis() - mStartActivityRequestedTime)
- >= START_ACTIVITY_REQUEST_TIMEOUT_MS;
- }
-
- /**
* Handles changes in menu visibility.
*/
- private void onMenuStateChanged(int menuState, boolean resize, Runnable callback) {
+ void onMenuStateChanged(int menuState, boolean resize, Runnable callback) {
if (DEBUG) {
Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
+ " menuState=" + menuState + " resize=" + resize
@@ -556,25 +357,14 @@
mMenuState = menuState;
}
- private void setStartActivityRequested(boolean requested) {
- mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
- mStartActivityRequested = requested;
- mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0;
- }
-
/**
* Handles a pointer event sent from pip input consumer.
*/
void handlePointerEvent(MotionEvent ev) {
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_POINTER_EVENT;
- m.obj = ev;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not dispatch touch event", e);
- }
+ if (ev.isTouchEvent()) {
+ mPipMenuView.dispatchTouchEvent(ev);
+ } else {
+ mPipMenuView.dispatchGenericMotionEvent(ev);
}
}
@@ -582,15 +372,14 @@
* Tell the PIP Menu to recalculate its layout given its current position on the display.
*/
public void updateMenuLayout(Rect bounds) {
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_UPDATE_MENU_LAYOUT;
- m.obj = bounds;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not dispatch touch event", e);
- }
+ final boolean isMenuVisible = isMenuVisible();
+ if (DEBUG) {
+ Log.d(TAG, "updateMenuLayout() state=" + mMenuState
+ + " isMenuVisible=" + isMenuVisible
+ + " callers=\n" + Debug.getCallers(5, " "));
+ }
+ if (isMenuVisible) {
+ mPipMenuView.updateMenuLayout(bounds);
}
}
@@ -598,9 +387,7 @@
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
pw.println(innerPrefix + "mMenuState=" + mMenuState);
- pw.println(innerPrefix + "mToActivityMessenger=" + mToActivityMessenger);
+ pw.println(innerPrefix + "mPipMenuView=" + mPipMenuView);
pw.println(innerPrefix + "mListeners=" + mListeners.size());
- pw.println(innerPrefix + "mStartActivityRequested=" + mStartActivityRequested);
- pw.println(innerPrefix + "mStartActivityRequestedTime=" + mStartActivityRequestedTime);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
new file mode 100644
index 0000000..993bfe0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2020 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.pip.phone;
+
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.app.PendingIntent.CanceledException;
+import android.app.RemoteAction;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Pair;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Translucent window that gets started on top of a task in PIP to allow the user to control it.
+ */
+public class PipMenuView extends FrameLayout {
+
+ private static final String TAG = "PipMenuView";
+
+ private static final int MESSAGE_INVALID_TYPE = -1;
+ public static final int MESSAGE_MENU_EXPANDED = 8;
+
+ private static final int INITIAL_DISMISS_DELAY = 3500;
+ private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
+ private static final long MENU_FADE_DURATION = 125;
+ private static final long MENU_SLOW_FADE_DURATION = 175;
+ private static final long MENU_SHOW_ON_EXPAND_START_DELAY = 30;
+
+ private static final float MENU_BACKGROUND_ALPHA = 0.3f;
+ private static final float DISMISS_BACKGROUND_ALPHA = 0.6f;
+
+ private static final float DISABLED_ACTION_ALPHA = 0.54f;
+
+ private static final boolean ENABLE_RESIZE_HANDLE = false;
+
+ private int mMenuState;
+ private boolean mResize = true;
+ private boolean mAllowMenuTimeout = true;
+ private boolean mAllowTouches = true;
+
+ private final List<RemoteAction> mActions = new ArrayList<>();
+
+ private AccessibilityManager mAccessibilityManager;
+ private Drawable mBackgroundDrawable;
+ private View mMenuContainer;
+ private LinearLayout mActionsGroup;
+ private int mBetweenActionPaddingLand;
+
+ private AnimatorSet mMenuContainerAnimator;
+ private PipMenuActivityController mController;
+
+ private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float alpha = (float) animation.getAnimatedValue();
+ mBackgroundDrawable.setAlpha((int) (MENU_BACKGROUND_ALPHA * alpha * 255));
+ }
+ };
+
+ private Handler mHandler = new Handler();
+
+ private final Runnable mHideMenuRunnable = this::hideMenu;
+
+ protected View mViewRoot;
+ protected View mSettingsButton;
+ protected View mDismissButton;
+ protected View mResizeHandle;
+ protected View mTopEndContainer;
+ protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
+
+ public PipMenuView(Context context, PipMenuActivityController controller) {
+ super(context, null, 0);
+ mContext = context;
+ mController = controller;
+
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+ inflate(context, R.layout.pip_menu, this);
+
+ mBackgroundDrawable = new ColorDrawable(Color.BLACK);
+ mBackgroundDrawable.setAlpha(0);
+ mViewRoot = findViewById(R.id.background);
+ mViewRoot.setBackground(mBackgroundDrawable);
+ mMenuContainer = findViewById(R.id.menu_container);
+ mMenuContainer.setAlpha(0);
+ mTopEndContainer = findViewById(R.id.top_end_container);
+ mSettingsButton = findViewById(R.id.settings);
+ mSettingsButton.setAlpha(0);
+ mSettingsButton.setOnClickListener((v) -> {
+ if (v.getAlpha() != 0) {
+ showSettings();
+ }
+ });
+ mDismissButton = findViewById(R.id.dismiss);
+ mDismissButton.setAlpha(0);
+ mDismissButton.setOnClickListener(v -> dismissPip());
+ findViewById(R.id.expand_button).setOnClickListener(v -> {
+ if (mMenuContainer.getAlpha() != 0) {
+ expandPip();
+ }
+ });
+ // TODO (b/161710689): Remove this once focusability for Windowless window is working
+ findViewById(R.id.expand_button).setFocusable(false);
+ mDismissButton.setFocusable(false);
+ mSettingsButton.setFocusable(false);
+
+ mResizeHandle = findViewById(R.id.resize_handle);
+ mResizeHandle.setAlpha(0);
+ mActionsGroup = findViewById(R.id.actions_group);
+ mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
+ R.dimen.pip_between_action_padding_land);
+ mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(mContext);
+ mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer,
+ mResizeHandle, mSettingsButton, mDismissButton);
+
+ initAccessibility();
+ }
+
+ private void initAccessibility() {
+ this.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ String label = getResources().getString(R.string.pip_menu_title);
+ info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, label));
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (action == ACTION_CLICK && mMenuState == MENU_STATE_CLOSE) {
+ mController.onPipShowMenu();
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+ });
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
+ hideMenu();
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (!mAllowTouches) {
+ return false;
+ }
+
+ if (mAllowMenuTimeout) {
+ repostDelayedHide(POST_INTERACTION_DISMISS_DELAY);
+ }
+
+ return super.dispatchTouchEvent(ev);
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ if (mAllowMenuTimeout) {
+ repostDelayedHide(POST_INTERACTION_DISMISS_DELAY);
+ }
+
+ return super.dispatchGenericMotionEvent(event);
+ }
+
+ void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
+ boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
+ mAllowMenuTimeout = allowMenuTimeout;
+ if (mMenuState != menuState) {
+ // Disallow touches if the menu needs to resize while showing, and we are transitioning
+ // to/from a full menu state.
+ boolean disallowTouchesUntilAnimationEnd = resizeMenuOnShow
+ && (mMenuState == MENU_STATE_FULL || menuState == MENU_STATE_FULL);
+ mAllowTouches = !disallowTouchesUntilAnimationEnd;
+ cancelDelayedHide();
+ updateActionViews(stackBounds);
+ if (mMenuContainerAnimator != null) {
+ mMenuContainerAnimator.cancel();
+ }
+ mMenuContainerAnimator = new AnimatorSet();
+ ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
+ mMenuContainer.getAlpha(), 1f);
+ menuAnim.addUpdateListener(mMenuBgUpdateListener);
+ ObjectAnimator settingsAnim = ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA,
+ mSettingsButton.getAlpha(), 1f);
+ ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
+ mDismissButton.getAlpha(), 1f);
+ ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
+ mResizeHandle.getAlpha(),
+ ENABLE_RESIZE_HANDLE && menuState == MENU_STATE_CLOSE && showResizeHandle
+ ? 1f : 0f);
+ if (menuState == MENU_STATE_FULL) {
+ mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
+ resizeAnim);
+ } else {
+ mMenuContainerAnimator.playTogether(dismissAnim, resizeAnim);
+ }
+ mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
+ mMenuContainerAnimator.setDuration(menuState == MENU_STATE_CLOSE
+ ? MENU_FADE_DURATION
+ : MENU_SLOW_FADE_DURATION);
+ if (allowMenuTimeout) {
+ mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ repostDelayedHide(INITIAL_DISMISS_DELAY);
+ }
+ });
+ }
+ if (withDelay) {
+ // starts the menu container animation after window expansion is completed
+ notifyMenuStateChange(menuState, resizeMenuOnShow, () -> {
+ if (mMenuContainerAnimator == null) {
+ return;
+ }
+ mMenuContainerAnimator.setStartDelay(MENU_SHOW_ON_EXPAND_START_DELAY);
+ mMenuContainerAnimator.start();
+ });
+ } else {
+ notifyMenuStateChange(menuState, resizeMenuOnShow, null);
+ mMenuContainerAnimator.start();
+ }
+ } else {
+ // If we are already visible, then just start the delayed dismiss and unregister any
+ // existing input consumers from the previous drag
+ if (allowMenuTimeout) {
+ repostDelayedHide(POST_INTERACTION_DISMISS_DELAY);
+ }
+ }
+ }
+
+ /**
+ * Different from {@link #hideMenu()}, this function does not try to finish this menu activity
+ * and instead, it fades out the controls by setting the alpha to 0 directly without menu
+ * visibility callbacks invoked.
+ */
+ void fadeOutMenu() {
+ mMenuContainer.setAlpha(0f);
+ mSettingsButton.setAlpha(0f);
+ mDismissButton.setAlpha(0f);
+ mResizeHandle.setAlpha(0f);
+ }
+
+ void pokeMenu() {
+ cancelDelayedHide();
+ }
+
+ void onPipAnimationEnded() {
+ mAllowTouches = true;
+ }
+
+ void updateMenuLayout(Rect bounds) {
+ mPipMenuIconsAlgorithm.onBoundsChanged(bounds);
+ }
+
+ void hideMenu() {
+ hideMenu(null);
+ }
+
+ void hideMenu(Runnable animationEndCallback) {
+ hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false);
+ }
+
+ private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
+ boolean animate) {
+ if (mMenuState != MENU_STATE_NONE) {
+ cancelDelayedHide();
+ if (notifyMenuVisibility) {
+ notifyMenuStateChange(MENU_STATE_NONE, mResize, null);
+ }
+ mMenuContainerAnimator = new AnimatorSet();
+ ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
+ mMenuContainer.getAlpha(), 0f);
+ menuAnim.addUpdateListener(mMenuBgUpdateListener);
+ ObjectAnimator settingsAnim = ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA,
+ mSettingsButton.getAlpha(), 0f);
+ ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
+ mDismissButton.getAlpha(), 0f);
+ ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
+ mResizeHandle.getAlpha(), 0f);
+ mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim);
+ mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
+ mMenuContainerAnimator.setDuration(animate ? MENU_FADE_DURATION : 0);
+ mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (animationFinishedRunnable != null) {
+ animationFinishedRunnable.run();
+ }
+ }
+ });
+ mMenuContainerAnimator.start();
+ }
+ }
+
+ void setActions(Rect stackBounds, List<RemoteAction> actions) {
+ mActions.clear();
+ mActions.addAll(actions);
+ updateActionViews(stackBounds);
+ }
+
+ private void updateActionViews(Rect stackBounds) {
+ ViewGroup expandContainer = findViewById(R.id.expand_container);
+ ViewGroup actionsContainer = findViewById(R.id.actions_container);
+ actionsContainer.setOnTouchListener((v, ev) -> {
+ // Do nothing, prevent click through to parent
+ return true;
+ });
+
+ if (mActions.isEmpty() || mMenuState == MENU_STATE_CLOSE) {
+ actionsContainer.setVisibility(View.INVISIBLE);
+ } else {
+ actionsContainer.setVisibility(View.VISIBLE);
+ if (mActionsGroup != null) {
+ // Ensure we have as many buttons as actions
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ while (mActionsGroup.getChildCount() < mActions.size()) {
+ final ImageButton actionView = (ImageButton) inflater.inflate(
+ R.layout.pip_menu_action, mActionsGroup, false);
+ mActionsGroup.addView(actionView);
+ }
+
+ // Update the visibility of all views
+ for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
+ mActionsGroup.getChildAt(i).setVisibility(i < mActions.size()
+ ? View.VISIBLE
+ : View.GONE);
+ }
+
+ // Recreate the layout
+ final boolean isLandscapePip = stackBounds != null
+ && (stackBounds.width() > stackBounds.height());
+ for (int i = 0; i < mActions.size(); i++) {
+ final RemoteAction action = mActions.get(i);
+ final ImageButton actionView = (ImageButton) mActionsGroup.getChildAt(i);
+
+ // TODO: Check if the action drawable has changed before we reload it
+ action.getIcon().loadDrawableAsync(mContext, d -> {
+ d.setTint(Color.WHITE);
+ actionView.setImageDrawable(d);
+ }, mHandler);
+ actionView.setContentDescription(action.getContentDescription());
+ if (action.isEnabled()) {
+ actionView.setOnClickListener(v -> {
+ mHandler.post(() -> {
+ try {
+ action.getActionIntent().send();
+ } catch (CanceledException e) {
+ Log.w(TAG, "Failed to send action", e);
+ }
+ });
+ });
+ }
+ actionView.setEnabled(action.isEnabled());
+ actionView.setAlpha(action.isEnabled() ? 1f : DISABLED_ACTION_ALPHA);
+
+ // Update the margin between actions
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+ actionView.getLayoutParams();
+ lp.leftMargin = (isLandscapePip && i > 0) ? mBetweenActionPaddingLand : 0;
+ }
+ }
+
+ // Update the expand container margin to adjust the center of the expand button to
+ // account for the existence of the action container
+ FrameLayout.LayoutParams expandedLp =
+ (FrameLayout.LayoutParams) expandContainer.getLayoutParams();
+ expandedLp.topMargin = getResources().getDimensionPixelSize(
+ R.dimen.pip_action_padding);
+ expandedLp.bottomMargin = getResources().getDimensionPixelSize(
+ R.dimen.pip_expand_container_edge_margin);
+ expandContainer.requestLayout();
+ }
+ }
+
+ void updateDismissFraction(float fraction) {
+ int alpha;
+ final float menuAlpha = 1 - fraction;
+ if (mMenuState == MENU_STATE_FULL) {
+ mMenuContainer.setAlpha(menuAlpha);
+ mSettingsButton.setAlpha(menuAlpha);
+ mDismissButton.setAlpha(menuAlpha);
+ final float interpolatedAlpha =
+ MENU_BACKGROUND_ALPHA * menuAlpha + DISMISS_BACKGROUND_ALPHA * fraction;
+ alpha = (int) (interpolatedAlpha * 255);
+ } else {
+ if (mMenuState == MENU_STATE_CLOSE) {
+ mDismissButton.setAlpha(menuAlpha);
+ }
+ alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
+ }
+ mBackgroundDrawable.setAlpha(alpha);
+ }
+
+ private void notifyMenuStateChange(int menuState, boolean resize, Runnable callback) {
+ mMenuState = menuState;
+ mController.onMenuStateChanged(menuState, resize, callback);
+ }
+
+ private void expandPip() {
+ // Do not notify menu visibility when hiding the menu, the controller will do this when it
+ // handles the message
+ hideMenu(mController::onPipExpand, false /* notifyMenuVisibility */, true /* animate */);
+ }
+
+ private void dismissPip() {
+ // Since tapping on the close-button invokes a double-tap wait callback in PipTouchHandler,
+ // we want to disable animating the fadeout animation of the buttons in order to call on
+ // PipTouchHandler#onPipDismiss fast enough.
+ final boolean animate = mMenuState != MENU_STATE_CLOSE;
+ // Do not notify menu visibility when hiding the menu, the controller will do this when it
+ // handles the message
+ hideMenu(mController::onPipDismiss, false /* notifyMenuVisibility */, animate);
+ }
+
+ private void showSettings() {
+ final Pair<ComponentName, Integer> topPipActivityInfo =
+ PipUtils.getTopPipActivity(mContext, ActivityManager.getService());
+ if (topPipActivityInfo.first != null) {
+ final UserHandle user = UserHandle.of(topPipActivityInfo.second);
+ final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS,
+ Uri.fromParts("package", topPipActivityInfo.first.getPackageName(), null));
+ settingsIntent.putExtra(Intent.EXTRA_USER_HANDLE, user);
+ settingsIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(settingsIntent);
+ }
+ }
+
+ private void cancelDelayedHide() {
+ mHandler.removeCallbacks(mHideMenuRunnable);
+ }
+
+ private void repostDelayedHide(int delay) {
+ int recommendedTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(delay,
+ FLAG_CONTENT_ICONS | FLAG_CONTENT_CONTROLS);
+ mHandler.removeCallbacks(mHideMenuRunnable);
+ mHandler.postDelayed(mHideMenuRunnable, recommendedTimeout);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 19138fdb..dcee2a5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -23,6 +23,8 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import android.view.Choreographer;
@@ -66,6 +68,8 @@
private PipMenuActivityController mMenuController;
private PipSnapAlgorithm mSnapAlgorithm;
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+
/** PIP's current bounds on the screen. */
private final Rect mBounds = new Rect();
@@ -128,8 +132,10 @@
SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> {
- mMenuController.updateMenuLayout(newBounds);
- mBounds.set(newBounds);
+ mMainHandler.post(() -> {
+ mMenuController.updateMenuLayout(newBounds);
+ mBounds.set(newBounds);
+ });
};
/**
@@ -253,7 +259,9 @@
mTemporaryBounds.set(toBounds);
mPipTaskOrganizer.scheduleUserResizePip(mBounds, mTemporaryBounds,
(Rect newBounds) -> {
- mMenuController.updateMenuLayout(newBounds);
+ mMainHandler.post(() -> {
+ mMenuController.updateMenuLayout(newBounds);
+ });
});
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index 2800bb9..f6853ec 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -111,6 +111,7 @@
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
private PipTaskOrganizer mPipTaskOrganizer;
+ private PipMenuActivityController mPipMenuActivityController;
private PipUiEventLogger mPipUiEventLogger;
private int mCtrlType;
@@ -119,7 +120,7 @@
PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig,
PipTaskOrganizer pipTaskOrganizer, Function<Rect, Rect> movementBoundsSupplier,
Runnable updateMovementBoundsRunnable, SysUiState sysUiState,
- PipUiEventLogger pipUiEventLogger) {
+ PipUiEventLogger pipUiEventLogger, PipMenuActivityController menuActivityController) {
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
@@ -129,6 +130,7 @@
mMovementBoundsSupplier = movementBoundsSupplier;
mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
mSysUiState = sysUiState;
+ mPipMenuActivityController = menuActivityController;
mPipUiEventLogger = pipUiEventLogger;
context.getDisplay().getRealSize(mMaxSize);
@@ -298,6 +300,7 @@
float x = ev.getX();
float y = ev.getY();
if (action == MotionEvent.ACTION_DOWN) {
+ final Rect currentPipBounds = mMotionHelper.getBounds();
mLastResizeBounds.setEmpty();
mAllowGesture = isInValidSysUiState() && isWithinTouchRegion((int) x, (int) y);
if (mAllowGesture) {
@@ -305,6 +308,10 @@
mDownPoint.set(x, y);
mLastDownBounds.set(mMotionHelper.getBounds());
}
+ if (!currentPipBounds.contains((int) ev.getX(), (int) ev.getY())
+ && mPipMenuActivityController.isMenuVisible()) {
+ mPipMenuActivityController.hideMenu();
+ }
} else if (mAllowGesture) {
switch (action) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 1b84c14..9693f23 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -230,7 +230,7 @@
mPipResizeGestureHandler =
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
deviceConfig, pipTaskOrganizer, this::getMovementBounds,
- this::updateMovementBounds, sysUiState, pipUiEventLogger);
+ this::updateMovementBounds, sysUiState, pipUiEventLogger, menuController);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()),
@@ -773,10 +773,7 @@
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
private void updateDismissFraction() {
- // Skip updating the dismiss fraction when the IME is showing. This is to work around an
- // issue where starting the menu activity for the dismiss overlay will steal the window
- // focus, which closes the IME.
- if (mMenuController != null && !mIsImeShowing) {
+ if (mMenuController != null) {
Rect bounds = mMotionHelper.getBounds();
final float target = mInsetBounds.bottom;
float fraction = 0f;
@@ -784,7 +781,7 @@
final float distance = bounds.bottom - target;
fraction = Math.min(distance / bounds.height(), 1f);
}
- if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuActivityVisible()) {
+ if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuVisible()) {
// Update if the fraction > 0, or if fraction == 0 and the menu was already visible
mMenuController.setDismissFraction(fraction);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java b/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java
deleted file mode 100644
index 114c30e..0000000
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.pip.phone.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface PipMenuActivityClass {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 7b45476..6a2ca44 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -22,8 +22,6 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.pip.phone.PipMenuActivity;
-import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.stackdivider.SplitScreenController;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -50,14 +48,6 @@
return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
}
- /** TODO(b/150319024): PipMenuActivity will move to a Window */
- @SysUISingleton
- @PipMenuActivityClass
- @Provides
- static Class<?> providePipMenuActivityClass() {
- return PipMenuActivity.class;
- }
-
@SysUISingleton
@Provides
static SplitScreen provideSplitScreen(Context context,