diff options
235 files changed, 7025 insertions, 1256 deletions
diff --git a/Android.bp b/Android.bp index 557c3209248d..632f49da5df9 100644 --- a/Android.bp +++ b/Android.bp @@ -292,13 +292,13 @@ filegroup { java_library { name: "framework-updatable-stubs-module_libs_api", static_libs: [ - "framework-media-stubs-module_libs_api", - "framework-mediaprovider-stubs-module_libs_api", - "framework-permission-stubs-module_libs_api", - "framework-sdkextensions-stubs-module_libs_api", - "framework-statsd-stubs-module_libs_api", - "framework-tethering-stubs-module_libs_api", - "framework-wifi-stubs-module_libs_api", + "framework-media.stubs.module_lib", + "framework-mediaprovider.stubs.module_lib", + "framework-permission.stubs.module_lib", + "framework-sdkextensions.stubs.module_lib", + "framework-statsd.stubs.module_lib", + "framework-tethering.stubs.module_lib", + "framework-wifi.stubs.module_lib", ], sdk_version: "module_current", visibility: [":__pkg__"], diff --git a/StubLibraries.bp b/StubLibraries.bp index c0197c4b2acf..ef4e202fdfe2 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -329,13 +329,13 @@ java_library_static { srcs: [ ":api-stubs-docs-non-updatable" ], static_libs: [ "conscrypt.module.public.api.stubs", - "framework-media-stubs-publicapi", - "framework-mediaprovider-stubs-publicapi", - "framework-permission-stubs-publicapi", - "framework-sdkextensions-stubs-publicapi", - "framework-statsd-stubs-publicapi", - "framework-tethering-stubs-publicapi", - "framework-wifi-stubs-publicapi", + "framework-media.stubs", + "framework-mediaprovider.stubs", + "framework-permission.stubs", + "framework-sdkextensions.stubs", + "framework-statsd.stubs", + "framework-tethering.stubs", + "framework-wifi.stubs", "private-stub-annotations-jar", ], defaults: ["android_defaults_stubs_current"], @@ -359,13 +359,13 @@ java_library_static { srcs: [ ":system-api-stubs-docs-non-updatable" ], static_libs: [ "conscrypt.module.public.api.stubs", - "framework-media-stubs-systemapi", - "framework-mediaprovider-stubs-systemapi", - "framework-permission-stubs-systemapi", - "framework-sdkextensions-stubs-systemapi", - "framework-statsd-stubs-systemapi", - "framework-tethering-stubs-systemapi", - "framework-wifi-stubs-systemapi", + "framework-media.stubs.system", + "framework-mediaprovider.stubs.system", + "framework-permission.stubs.system", + "framework-sdkextensions.stubs.system", + "framework-statsd.stubs.system", + "framework-tethering.stubs.system", + "framework-wifi.stubs.system", "private-stub-annotations-jar", ], defaults: ["android_defaults_stubs_current"], diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index ac501a510e80..4417b681efc3 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -96,11 +96,6 @@ java_sdk_library { ":updatable-media-srcs", ], - // TODO(b/155480189) - Remove naming_scheme once references have been resolved. - // Temporary java_sdk_library component naming scheme to use to ease the transition from separate - // modules to java_sdk_library. - naming_scheme: "framework-modules", - libs: [ "framework_media_annotation", ], diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java index d0692e44a564..070b13b9e592 100644 --- a/apex/media/framework/java/android/media/MediaParser.java +++ b/apex/media/framework/java/android/media/MediaParser.java @@ -402,9 +402,9 @@ public final class MediaParser { * onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the * last byte belonging to the sample whose metadata is being passed. * @param cryptoInfo Encryption data required to decrypt the sample. May be null for - * unencrypted samples. MediaParser may reuse {@link CryptoInfo} instances to avoid - * allocations, so implementations of this method must not write to or keep reference to - * the fields of this parameter. + * unencrypted samples. Implementors should treat any output {@link CryptoInfo} + * instances as immutable. MediaParser will not modify any output {@code cryptoInfos} + * and implementors should not modify them either. */ void onSampleCompleted( int trackIndex, @@ -1409,23 +1409,28 @@ public final class MediaParser { private class TrackOutputAdapter implements TrackOutput { private final int mTrackIndex; - private final CryptoInfo mCryptoInfo; + + private CryptoInfo mLastOutputCryptoInfo; + private CryptoInfo.Pattern mLastOutputEncryptionPattern; + private CryptoData mLastReceivedCryptoData; @EncryptionDataReadState private int mEncryptionDataReadState; private int mEncryptionDataSizeToSubtractFromSampleDataSize; private int mEncryptionVectorSize; + private byte[] mScratchIvSpace; + private int mSubsampleEncryptionDataSize; + private int[] mScratchSubsampleEncryptedBytesCount; + private int[] mScratchSubsampleClearBytesCount; private boolean mHasSubsampleEncryptionData; - private CryptoInfo.Pattern mEncryptionPattern; private int mSkippedSupplementalDataBytes; private TrackOutputAdapter(int trackIndex) { mTrackIndex = trackIndex; - mCryptoInfo = new CryptoInfo(); - mCryptoInfo.iv = new byte[16]; // Size documented in CryptoInfo. - mCryptoInfo.numBytesOfClearData = new int[0]; - mCryptoInfo.numBytesOfEncryptedData = new int[0]; + mScratchIvSpace = new byte[16]; // Size documented in CryptoInfo. + mScratchSubsampleEncryptedBytesCount = new int[32]; + mScratchSubsampleClearBytesCount = new int[32]; mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE; - mEncryptionPattern = + mLastOutputEncryptionPattern = new CryptoInfo.Pattern(/* blocksToEncrypt= */ 0, /* blocksToSkip= */ 0); } @@ -1466,35 +1471,39 @@ public final class MediaParser { mEncryptionDataReadState = STATE_READING_INIT_VECTOR; break; case STATE_READING_INIT_VECTOR: - Arrays.fill(mCryptoInfo.iv, (byte) 0); // Ensure 0-padding. - data.readBytes(mCryptoInfo.iv, /* offset= */ 0, mEncryptionVectorSize); + Arrays.fill(mScratchIvSpace, (byte) 0); // Ensure 0-padding. + data.readBytes(mScratchIvSpace, /* offset= */ 0, mEncryptionVectorSize); length -= mEncryptionVectorSize; if (mHasSubsampleEncryptionData) { mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE; } else { - mCryptoInfo.numSubSamples = 0; + mSubsampleEncryptionDataSize = 0; mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE; } break; case STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE: - int numSubSamples = data.readUnsignedShort(); - mCryptoInfo.numSubSamples = numSubSamples; - if (mCryptoInfo.numBytesOfClearData.length < numSubSamples) { - mCryptoInfo.numBytesOfClearData = new int[numSubSamples]; - mCryptoInfo.numBytesOfEncryptedData = new int[numSubSamples]; + mSubsampleEncryptionDataSize = data.readUnsignedShort(); + if (mScratchSubsampleClearBytesCount.length + < mSubsampleEncryptionDataSize) { + mScratchSubsampleClearBytesCount = + new int[mSubsampleEncryptionDataSize]; + mScratchSubsampleEncryptedBytesCount = + new int[mSubsampleEncryptionDataSize]; } length -= 2; mEncryptionDataSizeToSubtractFromSampleDataSize += - 2 + numSubSamples * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY; + 2 + + mSubsampleEncryptionDataSize + * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY; mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_DATA; break; case STATE_READING_SUBSAMPLE_ENCRYPTION_DATA: - for (int i = 0; i < mCryptoInfo.numSubSamples; i++) { - mCryptoInfo.numBytesOfClearData[i] = data.readUnsignedShort(); - mCryptoInfo.numBytesOfEncryptedData[i] = data.readInt(); + for (int i = 0; i < mSubsampleEncryptionDataSize; i++) { + mScratchSubsampleClearBytesCount[i] = data.readUnsignedShort(); + mScratchSubsampleEncryptedBytesCount[i] = data.readInt(); } length -= - mCryptoInfo.numSubSamples + mSubsampleEncryptionDataSize * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY; mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE; if (length != 0) { @@ -1536,24 +1545,71 @@ public final class MediaParser { if (cryptoData == null) { // The sample is not encrypted. return null; + } else if (mInBandCryptoInfo) { + if (cryptoData != mLastReceivedCryptoData) { + mLastOutputCryptoInfo = + createNewCryptoInfoAndPopulateWithCryptoData(cryptoData); + } + } else /* We must populate the full CryptoInfo. */ { + // CryptoInfo.pattern is not accessible to the user, so the user needs to feed + // this CryptoInfo directly to MediaCodec. We need to create a new CryptoInfo per + // sample because of per-sample initialization vector changes. + CryptoInfo newCryptoInfo = createNewCryptoInfoAndPopulateWithCryptoData(cryptoData); + newCryptoInfo.iv = Arrays.copyOf(mScratchIvSpace, mScratchIvSpace.length); + boolean canReuseSubsampleInfo = + mLastOutputCryptoInfo != null + && mLastOutputCryptoInfo.numSubSamples + == mSubsampleEncryptionDataSize; + for (int i = 0; i < mSubsampleEncryptionDataSize && canReuseSubsampleInfo; i++) { + canReuseSubsampleInfo = + mLastOutputCryptoInfo.numBytesOfClearData[i] + == mScratchSubsampleClearBytesCount[i] + && mLastOutputCryptoInfo.numBytesOfEncryptedData[i] + == mScratchSubsampleEncryptedBytesCount[i]; + } + newCryptoInfo.numSubSamples = mSubsampleEncryptionDataSize; + if (canReuseSubsampleInfo) { + newCryptoInfo.numBytesOfClearData = mLastOutputCryptoInfo.numBytesOfClearData; + newCryptoInfo.numBytesOfEncryptedData = + mLastOutputCryptoInfo.numBytesOfEncryptedData; + } else { + newCryptoInfo.numBytesOfClearData = + Arrays.copyOf( + mScratchSubsampleClearBytesCount, mSubsampleEncryptionDataSize); + newCryptoInfo.numBytesOfEncryptedData = + Arrays.copyOf( + mScratchSubsampleEncryptedBytesCount, + mSubsampleEncryptionDataSize); + } + mLastOutputCryptoInfo = newCryptoInfo; } - mCryptoInfo.key = cryptoData.encryptionKey; - // ExoPlayer modes match MediaCodec modes. - mCryptoInfo.mode = cryptoData.cryptoMode; - if (cryptoData.clearBlocks != 0) { - // Content is pattern-encrypted. - mCryptoInfo.setPattern(mEncryptionPattern); - mEncryptionPattern.set(cryptoData.encryptedBlocks, cryptoData.clearBlocks); - } else { - mCryptoInfo.setPattern(null); + mLastReceivedCryptoData = cryptoData; + return mLastOutputCryptoInfo; + } + + private CryptoInfo createNewCryptoInfoAndPopulateWithCryptoData(CryptoData cryptoData) { + CryptoInfo cryptoInfo = new CryptoInfo(); + cryptoInfo.key = cryptoData.encryptionKey; + cryptoInfo.mode = cryptoData.cryptoMode; + if (cryptoData.clearBlocks != mLastOutputEncryptionPattern.getSkipBlocks() + || cryptoData.encryptedBlocks + != mLastOutputEncryptionPattern.getEncryptBlocks()) { + mLastOutputEncryptionPattern = + new CryptoInfo.Pattern(cryptoData.encryptedBlocks, cryptoData.clearBlocks); } - return mCryptoInfo; + cryptoInfo.setPattern(mLastOutputEncryptionPattern); + return cryptoInfo; } private void outputSampleData(ParsableByteArray data, int length) { mScratchParsableByteArrayAdapter.resetWithByteArray(data, length); try { - mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchParsableByteArrayAdapter); + // Read all bytes from data. ExoPlayer extractors expect all sample data to be + // consumed by TrackOutput implementations when passing a ParsableByteArray. + while (mScratchParsableByteArrayAdapter.getLength() > 0) { + mOutputConsumer.onSampleDataFound( + mTrackIndex, mScratchParsableByteArrayAdapter); + } } catch (IOException e) { // Unexpected. throw new RuntimeException(e); diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp index 732caecbd4a7..be553feb1d34 100644 --- a/apex/permission/framework/Android.bp +++ b/apex/permission/framework/Android.bp @@ -38,11 +38,6 @@ java_sdk_library { ":framework-permission-sources", ], - // TODO(b/155480189) - Remove naming_scheme once references have been resolved. - // Temporary java_sdk_library component naming scheme to use to ease the transition from separate - // modules to java_sdk_library. - naming_scheme: "framework-modules", - apex_available: [ "com.android.permission", "test_com.android.permission", diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp index 78496c4074f8..1f479963eaa9 100644 --- a/apex/statsd/framework/Android.bp +++ b/apex/statsd/framework/Android.bp @@ -51,11 +51,6 @@ java_sdk_library { defaults: ["framework-module-defaults"], installable: true, - // TODO(b/155480189) - Remove naming_scheme once references have been resolved. - // Temporary java_sdk_library component naming scheme to use to ease the transition from separate - // modules to java_sdk_library. - naming_scheme: "framework-modules", - srcs: [ ":framework-statsd-sources", ], diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java index d2c6c095b81f..a7d20572ca96 100644 --- a/apex/statsd/framework/java/android/app/StatsManager.java +++ b/apex/statsd/framework/java/android/app/StatsManager.java @@ -561,7 +561,15 @@ public final class StatsManager { try { resultReceiver.pullFinished(atomTag, success, parcels); } catch (RemoteException e) { - Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId); + Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId + + " due to TransactionTooLarge. Calling pullFinish with no data"); + StatsEventParcel[] emptyData = new StatsEventParcel[0]; + try { + resultReceiver.pullFinished(atomTag, /*success=*/false, emptyData); + } catch (RemoteException nestedException) { + Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId + + " with empty payload"); + } } }); } finally { diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 3bcabe56f89e..bb2de17b42f3 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -349,6 +349,25 @@ EGLConfig BootAnimation::getEglConfig(const EGLDisplay& display) { return config; } +ui::Size BootAnimation::limitSurfaceSize(int width, int height) const { + ui::Size limited(width, height); + bool wasLimited = false; + const float aspectRatio = float(width) / float(height); + if (mMaxWidth != 0 && width > mMaxWidth) { + limited.height = mMaxWidth / aspectRatio; + limited.width = mMaxWidth; + wasLimited = true; + } + if (mMaxHeight != 0 && limited.height > mMaxHeight) { + limited.height = mMaxHeight; + limited.width = mMaxHeight * aspectRatio; + wasLimited = true; + } + SLOGV_IF(wasLimited, "Surface size has been limited to [%dx%d] from [%dx%d]", + limited.width, limited.height, width, height); + return limited; +} + status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); @@ -362,8 +381,10 @@ status_t BootAnimation::readyToRun() { if (error != NO_ERROR) return error; - const ui::Size& resolution = displayConfig.resolution; - + mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0); + mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0); + ui::Size resolution = displayConfig.resolution; + resolution = limitSurfaceSize(resolution.width, resolution.height); // create the native surface sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"), resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565); @@ -459,8 +480,9 @@ void BootAnimation::resizeSurface(int newWidth, int newHeight) { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(mDisplay, mSurface); - mWidth = newWidth; - mHeight = newHeight; + const auto limitedSize = limitSurfaceSize(newWidth, newHeight); + mWidth = limitedSize.width; + mHeight = limitedSize.height; SurfaceComposerClient::Transaction t; t.setSize(mFlingerSurfaceControl, mWidth, mHeight); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 36cd91bdee0d..6ba7fd450fbb 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -170,6 +170,7 @@ private: bool findBootAnimationFileInternal(const std::vector<std::string>& files); bool preloadAnimation(); EGLConfig getEglConfig(const EGLDisplay&); + ui::Size limitSurfaceSize(int width, int height) const; void resizeSurface(int newWidth, int newHeight); void checkExit(); @@ -181,6 +182,8 @@ private: Texture mAndroid[2]; int mWidth; int mHeight; + int mMaxWidth = 0; + int mMaxHeight = 0; int mCurrentInset; int mTargetInset; bool mUseNpotTextures = false; diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp index c829ccd11ec9..e9875baf58c7 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp +++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp @@ -37,7 +37,8 @@ CombinationConditionTracker::~CombinationConditionTracker() { bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConfig, const vector<sp<ConditionTracker>>& allConditionTrackers, const unordered_map<int64_t, int>& conditionIdIndexMap, - vector<bool>& stack) { + vector<bool>& stack, + vector<ConditionState>& initialConditionCache) { VLOG("Combination predicate init() %lld", (long long)mConditionId); if (mInitialized) { return true; @@ -73,9 +74,9 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf return false; } - - bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers, - conditionIdIndexMap, stack); + bool initChildSucceeded = + childTracker->init(allConditionConfig, allConditionTrackers, conditionIdIndexMap, + stack, initialConditionCache); if (!initChildSucceeded) { ALOGW("Child initialization failed %lld ", (long long)child); @@ -95,6 +96,11 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf childTracker->getLogTrackerIndex().end()); } + mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation, + initialConditionCache); + initialConditionCache[mIndex] = + evaluateCombinationCondition(mChildren, mLogicalOperation, initialConditionCache); + // unmark this node in the recursion stack. stack[mIndex] = false; diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h index e3d860127780..39ff0ab03266 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.h +++ b/cmds/statsd/src/condition/CombinationConditionTracker.h @@ -32,8 +32,8 @@ public: bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, - const std::unordered_map<int64_t, int>& conditionIdIndexMap, - std::vector<bool>& stack) override; + const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, + std::vector<ConditionState>& initialConditionCache) override; void evaluateCondition(const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues, diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h index f9a2c344c346..62736c8160bb 100644 --- a/cmds/statsd/src/condition/ConditionTracker.h +++ b/cmds/statsd/src/condition/ConditionTracker.h @@ -51,10 +51,12 @@ public: // need to call init() on children conditions) // conditionIdIndexMap: the mapping from condition id to its index. // stack: a bit map to keep track which nodes have been visited on the stack in the recursion. + // initialConditionCache: tracks initial conditions of all ConditionTrackers. virtual bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& conditionIdIndexMap, - std::vector<bool>& stack) = 0; + std::vector<bool>& stack, + std::vector<ConditionState>& initialConditionCache) = 0; // evaluate current condition given the new event. // event: the new log event diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index f23ec50abb50..efb4d4989425 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -95,9 +95,11 @@ SimpleConditionTracker::~SimpleConditionTracker() { bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig, const vector<sp<ConditionTracker>>& allConditionTrackers, const unordered_map<int64_t, int>& conditionIdIndexMap, - vector<bool>& stack) { + vector<bool>& stack, + vector<ConditionState>& initialConditionCache) { // SimpleConditionTracker does not have dependency on other conditions, thus we just return // if the initialization was successful. + initialConditionCache[mIndex] = mInitialValue; return mInitialized; } diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h index 5c5cc565f783..ea7f87bde2b8 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.h +++ b/cmds/statsd/src/condition/SimpleConditionTracker.h @@ -37,8 +37,8 @@ public: bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, - const std::unordered_map<int64_t, int>& conditionIdIndexMap, - std::vector<bool>& stack) override; + const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, + std::vector<ConditionState>& initialConditionCache) override; void evaluateCondition(const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues, diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index d865c2176c1e..573961276e5b 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -68,14 +68,14 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6; CountMetricProducer::CountMetricProducer( const ConfigKey& key, const CountMetric& metric, const int conditionIndex, - const sp<ConditionWizard>& wizard, const int64_t timeBaseNs, const int64_t startTimeNs, - + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, + const int64_t timeBaseNs, const int64_t startTimeNs, const unordered_map<int, shared_ptr<Activation>>& eventActivationMap, const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap, const vector<int>& slicedStateAtoms, const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) - : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap, - eventDeactivationMap, slicedStateAtoms, stateGroupMap) { + : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard, + eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap) { if (metric.has_bucket()) { mBucketSizeNs = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000; diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h index 26b3d3cc6722..f05fb061ccc1 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.h +++ b/cmds/statsd/src/metrics/CountMetricProducer.h @@ -43,7 +43,8 @@ class CountMetricProducer : public MetricProducer { public: CountMetricProducer( const ConfigKey& key, const CountMetric& countMetric, const int conditionIndex, - const sp<ConditionWizard>& wizard, const int64_t timeBaseNs, const int64_t startTimeNs, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, + const int64_t timeBaseNs, const int64_t startTimeNs, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {}, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap = {}, diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 663365924829..e9b043876d3d 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -64,15 +64,16 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6; DurationMetricProducer::DurationMetricProducer( const ConfigKey& key, const DurationMetric& metric, const int conditionIndex, - const size_t startIndex, const size_t stopIndex, const size_t stopAllIndex, - const bool nesting, const sp<ConditionWizard>& wizard, - const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs, + const vector<ConditionState>& initialConditionCache, const size_t startIndex, + const size_t stopIndex, const size_t stopAllIndex, const bool nesting, + const sp<ConditionWizard>& wizard, const FieldMatcher& internalDimensions, + const int64_t timeBaseNs, const int64_t startTimeNs, const unordered_map<int, shared_ptr<Activation>>& eventActivationMap, const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap, const vector<int>& slicedStateAtoms, const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) - : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap, - eventDeactivationMap, slicedStateAtoms, stateGroupMap), + : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard, + eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap), mAggregationType(metric.aggregation_type()), mStartIndex(startIndex), mStopIndex(stopIndex), diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h index 53f0f28c3386..bfe1010c89de 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.h +++ b/cmds/statsd/src/metrics/DurationMetricProducer.h @@ -40,10 +40,10 @@ class DurationMetricProducer : public MetricProducer { public: DurationMetricProducer( const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex, - const size_t startIndex, const size_t stopIndex, const size_t stopAllIndex, - const bool nesting, const sp<ConditionWizard>& wizard, - const FieldMatcher& internalDimensions, const int64_t timeBaseNs, - const int64_t startTimeNs, + const vector<ConditionState>& initialConditionCache, const size_t startIndex, + const size_t stopIndex, const size_t stopAllIndex, const bool nesting, + const sp<ConditionWizard>& wizard, const FieldMatcher& internalDimensions, + const int64_t timeBaseNs, const int64_t startTimeNs, const unordered_map<int, shared_ptr<Activation>>& eventActivationMap = {}, const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap = {}, const vector<int>& slicedStateAtoms = {}, diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index d68f64ae40b0..dc0036a687f3 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -54,13 +54,14 @@ const int FIELD_ID_ATOMS = 2; EventMetricProducer::EventMetricProducer( const ConfigKey& key, const EventMetric& metric, const int conditionIndex, - const sp<ConditionWizard>& wizard, const int64_t startTimeNs, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, + const int64_t startTimeNs, const unordered_map<int, shared_ptr<Activation>>& eventActivationMap, const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap, const vector<int>& slicedStateAtoms, const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) - : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard, eventActivationMap, - eventDeactivationMap, slicedStateAtoms, stateGroupMap) { + : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, initialConditionCache, wizard, + eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap) { if (metric.links().size() > 0) { for (const auto& link : metric.links()) { Metric2Condition mc; diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h index e8f2119a170c..bfb2de36fad4 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.h +++ b/cmds/statsd/src/metrics/EventMetricProducer.h @@ -35,7 +35,8 @@ class EventMetricProducer : public MetricProducer { public: EventMetricProducer( const ConfigKey& key, const EventMetric& eventMetric, const int conditionIndex, - const sp<ConditionWizard>& wizard, const int64_t startTimeNs, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, + const int64_t startTimeNs, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {}, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap = {}, diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 1d4d0b3a5e5d..020f4b638f4d 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -70,14 +70,15 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 8; GaugeMetricProducer::GaugeMetricProducer( const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex, - const sp<ConditionWizard>& wizard, const int whatMatcherIndex, - const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int triggerAtomId, - const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs, - const sp<StatsPullerManager>& pullerManager, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, + const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard, + const int pullTagId, const int triggerAtomId, const int atomId, const int64_t timeBaseNs, + const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager, const unordered_map<int, shared_ptr<Activation>>& eventActivationMap, const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) - : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap, - eventDeactivationMap, /*slicedStateAtoms=*/{}, /*stateGroupMap=*/{}), + : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard, + eventActivationMap, eventDeactivationMap, /*slicedStateAtoms=*/{}, + /*stateGroupMap=*/{}), mWhatMatcherIndex(whatMatcherIndex), mEventMatcherWizard(matcherWizard), mPullerManager(pullerManager), diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index 2eb584b097ea..2fc772b6b641 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -58,6 +58,7 @@ class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDa public: GaugeMetricProducer( const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int triggerAtomId, const int atomId, const int64_t timeBaseNs, diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index bb4f03e81e2e..cdd20cdd70f9 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -45,7 +45,8 @@ const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3; MetricProducer::MetricProducer( const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs, - const int conditionIndex, const sp<ConditionWizard>& wizard, + const int conditionIndex, const vector<ConditionState>& initialConditionCache, + const sp<ConditionWizard>& wizard, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap, @@ -56,7 +57,7 @@ MetricProducer::MetricProducer( mTimeBaseNs(timeBaseNs), mCurrentBucketStartTimeNs(timeBaseNs), mCurrentBucketNum(0), - mCondition(initialCondition(conditionIndex)), + mCondition(initialCondition(conditionIndex, initialConditionCache)), mConditionTrackerIndex(conditionIndex), mConditionSliced(false), mWizard(wizard), diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 9d37608149ce..be4cd6724bb1 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -129,7 +129,8 @@ struct SkippedBucket { class MetricProducer : public virtual android::RefBase, public virtual StateListener { public: MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs, - const int conditionIndex, const sp<ConditionWizard>& wizard, + const int conditionIndex, const vector<ConditionState>& initialConditionCache, + const sp<ConditionWizard>& wizard, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap, @@ -138,8 +139,9 @@ public: virtual ~MetricProducer(){}; - ConditionState initialCondition(const int conditionIndex) const { - return conditionIndex >= 0 ? ConditionState::kUnknown : ConditionState::kTrue; + ConditionState initialCondition(const int conditionIndex, + const vector<ConditionState>& initialConditionCache) const { + return conditionIndex >= 0 ? initialConditionCache[conditionIndex] : ConditionState::kTrue; } /** @@ -496,6 +498,8 @@ protected: FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions); FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges); + + FRIEND_TEST(MetricsManagerTest, TestInitialConditions); }; } // namespace statsd diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 71df710ee647..c0d117402314 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -78,6 +78,7 @@ const Value ZERO_DOUBLE((int64_t)0); // ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently ValueMetricProducer::ValueMetricProducer( const ConfigKey& key, const ValueMetric& metric, const int conditionIndex, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager, @@ -85,8 +86,9 @@ ValueMetricProducer::ValueMetricProducer( const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap, const vector<int>& slicedStateAtoms, const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) - : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard, - eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap), + : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, + conditionWizard, eventActivationMap, eventDeactivationMap, slicedStateAtoms, + stateGroupMap), mWhatMatcherIndex(whatMatcherIndex), mEventMatcherWizard(matcherWizard), mPullerManager(pullerManager), diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index aaf7df5c9771..3de5b99a2b09 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -52,6 +52,7 @@ class ValueMetricProducer : public virtual MetricProducer, public virtual PullDa public: ValueMetricProducer( const ConfigKey& key, const ValueMetric& valueMetric, const int conditionIndex, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs, diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index 210d382b1363..8917c36bb608 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -285,11 +285,14 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config, const unordered_map<int64_t, int>& logTrackerMap, unordered_map<int64_t, int>& conditionTrackerMap, vector<sp<ConditionTracker>>& allConditionTrackers, - unordered_map<int, std::vector<int>>& trackerToConditionMap) { + unordered_map<int, std::vector<int>>& trackerToConditionMap, + vector<ConditionState>& initialConditionCache) { vector<Predicate> conditionConfigs; const int conditionTrackerCount = config.predicate_size(); conditionConfigs.reserve(conditionTrackerCount); allConditionTrackers.reserve(conditionTrackerCount); + initialConditionCache.reserve(conditionTrackerCount); + std::fill(initialConditionCache.begin(), initialConditionCache.end(), ConditionState::kUnknown); for (int i = 0; i < conditionTrackerCount; i++) { const Predicate& condition = config.predicate(i); @@ -321,7 +324,7 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config, for (size_t i = 0; i < allConditionTrackers.size(); i++) { auto& conditionTracker = allConditionTrackers[i]; if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap, - stackTracker)) { + stackTracker, initialConditionCache)) { return false; } for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) { @@ -351,14 +354,14 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt } bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs, - const int64_t currentTimeNs, - const sp<StatsPullerManager>& pullerManager, + const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, const unordered_map<int64_t, int>& logTrackerMap, const unordered_map<int64_t, int>& conditionTrackerMap, const vector<sp<LogMatchingTracker>>& allAtomMatchers, const unordered_map<int64_t, int>& stateAtomIdMap, const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps, vector<sp<ConditionTracker>>& allConditionTrackers, + const vector<ConditionState>& initialConditionCache, vector<sp<MetricProducer>>& allMetricProducers, unordered_map<int, vector<int>>& conditionToMetricMap, unordered_map<int, vector<int>>& trackerToMetricMap, @@ -441,9 +444,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t eventDeactivationMap); if (!success) return false; - sp<MetricProducer> countProducer = new CountMetricProducer( - key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs, - eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap); + sp<MetricProducer> countProducer = + new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard, + timeBaseTimeNs, currentTimeNs, eventActivationMap, + eventDeactivationMap, slicedStateAtoms, stateGroupMap); allMetricProducers.push_back(countProducer); } @@ -547,10 +551,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t if (!success) return false; sp<MetricProducer> durationMetric = new DurationMetricProducer( - key, metric, conditionIndex, trackerIndices[0], trackerIndices[1], - trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs, - currentTimeNs, eventActivationMap, eventDeactivationMap, slicedStateAtoms, - stateGroupMap); + key, metric, conditionIndex, initialConditionCache, trackerIndices[0], + trackerIndices[1], trackerIndices[2], nesting, wizard, internalDimensions, + timeBaseTimeNs, currentTimeNs, eventActivationMap, eventDeactivationMap, + slicedStateAtoms, stateGroupMap); allMetricProducers.push_back(durationMetric); } @@ -593,9 +597,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t eventDeactivationMap); if (!success) return false; - sp<MetricProducer> eventMetric = new EventMetricProducer( - key, metric, conditionIndex, wizard, timeBaseTimeNs, eventActivationMap, - eventDeactivationMap); + sp<MetricProducer> eventMetric = + new EventMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard, + timeBaseTimeNs, eventActivationMap, eventDeactivationMap); allMetricProducers.push_back(eventMetric); } @@ -683,9 +687,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t if (!success) return false; sp<MetricProducer> valueProducer = new ValueMetricProducer( - key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId, - timeBaseTimeNs, currentTimeNs, pullerManager, eventActivationMap, - eventDeactivationMap, slicedStateAtoms, stateGroupMap); + key, metric, conditionIndex, initialConditionCache, wizard, trackerIndex, + matcherWizard, pullTagId, timeBaseTimeNs, currentTimeNs, pullerManager, + eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap); allMetricProducers.push_back(valueProducer); } @@ -778,9 +782,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t if (!success) return false; sp<MetricProducer> gaugeProducer = new GaugeMetricProducer( - key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId, - triggerAtomId, atomTagId, timeBaseTimeNs, currentTimeNs, pullerManager, - eventActivationMap, eventDeactivationMap); + key, metric, conditionIndex, initialConditionCache, wizard, trackerIndex, + matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseTimeNs, currentTimeNs, + pullerManager, eventActivationMap, eventDeactivationMap); allMetricProducers.push_back(gaugeProducer); } for (int i = 0; i < config.no_report_metric_size(); ++i) { @@ -930,6 +934,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& std::set<int64_t>& noReportMetricIds) { unordered_map<int64_t, int> logTrackerMap; unordered_map<int64_t, int> conditionTrackerMap; + vector<ConditionState> initialConditionCache; unordered_map<int64_t, int> metricProducerMap; unordered_map<int64_t, int> stateAtomIdMap; unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps; @@ -941,7 +946,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& VLOG("initLogMatchingTrackers succeed..."); if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers, - trackerToConditionMap)) { + trackerToConditionMap, initialConditionCache)) { ALOGE("initConditionTrackers failed"); return false; } @@ -952,10 +957,10 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& } if (!initMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager, logTrackerMap, conditionTrackerMap, allAtomMatchers, stateAtomIdMap, allStateGroupMaps, - allConditionTrackers, allMetricProducers, - conditionToMetricMap, trackerToMetricMap, metricProducerMap, - noReportMetricIds, activationAtomTrackerToMetricMap, - deactivationAtomTrackerToMetricMap, metricsWithActivation)) { + allConditionTrackers, initialConditionCache, allMetricProducers, + conditionToMetricMap, trackerToMetricMap, metricProducerMap, noReportMetricIds, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, + metricsWithActivation)) { ALOGE("initMetricProducers failed"); return false; } diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h index 6af7a9adca20..96b5c26ff789 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.h +++ b/cmds/statsd/src/metrics/metrics_manager_util.h @@ -60,12 +60,14 @@ bool initLogTrackers(const StatsdConfig& config, // [allConditionTrackers]: stores the sp to all the ConditionTrackers // [trackerToConditionMap]: contain the mapping from index of // log tracker to condition trackers that use the log tracker +// [initialConditionCache]: stores the initial conditions for each ConditionTracker bool initConditions(const ConfigKey& key, const StatsdConfig& config, const std::unordered_map<int64_t, int>& logTrackerMap, std::unordered_map<int64_t, int>& conditionTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, std::unordered_map<int, std::vector<int>>& trackerToConditionMap, - std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks); + std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks, + std::vector<ConditionState>& initialConditionCache); // Initialize State maps using State protos in the config. These maps will // eventually be passed to MetricProducers to initialize their state info. @@ -103,6 +105,7 @@ bool initMetrics( const unordered_map<int64_t, int>& stateAtomIdMap, const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps, vector<sp<ConditionTracker>>& allConditionTrackers, + const std::vector<ConditionState>& initialConditionCache, std::vector<sp<MetricProducer>>& allMetricProducers, std::unordered_map<int, std::vector<int>>& conditionToMetricMap, std::unordered_map<int, std::vector<int>>& trackerToMetricMap, diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp index b3b095bf4bff..6259757fe092 100644 --- a/cmds/statsd/tests/MetricsManager_test.cpp +++ b/cmds/statsd/tests/MetricsManager_test.cpp @@ -276,11 +276,157 @@ StatsdConfig buildCirclePredicates() { return config; } +StatsdConfig buildConfigWithDifferentPredicates() { + StatsdConfig config; + config.set_id(12345); + + auto pulledAtomMatcher = + CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE); + *config.add_atom_matcher() = pulledAtomMatcher; + auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = screenOnAtomMatcher; + auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = screenOffAtomMatcher; + auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher(); + *config.add_atom_matcher() = batteryNoneAtomMatcher; + auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher(); + *config.add_atom_matcher() = batteryUsbAtomMatcher; + + // Simple condition with InitialValue set to default (unknown). + auto screenOnUnknownPredicate = CreateScreenIsOnPredicate(); + *config.add_predicate() = screenOnUnknownPredicate; + + // Simple condition with InitialValue set to false. + auto screenOnFalsePredicate = config.add_predicate(); + screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse")); + SimplePredicate* simpleScreenOnFalsePredicate = + screenOnFalsePredicate->mutable_simple_predicate(); + simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id()); + simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id()); + simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE); + + // Simple condition with InitialValue set to false. + auto onBatteryFalsePredicate = config.add_predicate(); + onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse")); + SimplePredicate* simpleOnBatteryFalsePredicate = + onBatteryFalsePredicate->mutable_simple_predicate(); + simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id()); + simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id()); + simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE); + + // Combination condition with both simple condition InitialValues set to false. + auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate(); + screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse")); + screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation( + LogicalOperation::AND); + addPredicateToPredicateCombination(*screenOnFalsePredicate, + screenOnFalseOnBatteryFalsePredicate); + addPredicateToPredicateCombination(*onBatteryFalsePredicate, + screenOnFalseOnBatteryFalsePredicate); + + // Combination condition with one simple condition InitialValue set to unknown and one set to + // false. + auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate(); + screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse")); + screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation( + LogicalOperation::AND); + addPredicateToPredicateCombination(screenOnUnknownPredicate, + screenOnUnknownOnBatteryFalsePredicate); + addPredicateToPredicateCombination(*onBatteryFalsePredicate, + screenOnUnknownOnBatteryFalsePredicate); + + // Simple condition metric with initial value false. + ValueMetric* metric1 = config.add_value_metric(); + metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse")); + metric1->set_what(pulledAtomMatcher.id()); + *metric1->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric1->set_bucket(FIVE_MINUTES); + metric1->set_condition(screenOnFalsePredicate->id()); + + // Simple condition metric with initial value unknown. + ValueMetric* metric2 = config.add_value_metric(); + metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown")); + metric2->set_what(pulledAtomMatcher.id()); + *metric2->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric2->set_bucket(FIVE_MINUTES); + metric2->set_condition(screenOnUnknownPredicate.id()); + + // Combination condition metric with initial values false and false. + ValueMetric* metric3 = config.add_value_metric(); + metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse")); + metric3->set_what(pulledAtomMatcher.id()); + *metric3->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric3->set_bucket(FIVE_MINUTES); + metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id()); + + // Combination condition metric with initial values unknown and false. + ValueMetric* metric4 = config.add_value_metric(); + metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse")); + metric4->set_what(pulledAtomMatcher.id()); + *metric4->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric4->set_bucket(FIVE_MINUTES); + metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id()); + + return config; +} + bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) { return std::includes(set2.begin(), set2.end(), set1.begin(), set1.end()); } } // anonymous namespace +TEST(MetricsManagerTest, TestInitialConditions) { + UidMap uidMap; + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildConfigWithDifferentPredicates(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_TRUE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, allConditionTrackers, + allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, + trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, + deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation, + noReportMetricIds)); + ASSERT_EQ(4u, allMetricProducers.size()); + ASSERT_EQ(5u, allConditionTrackers.size()); + + ConditionKey queryKey; + vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated); + + allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache); + allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache); + EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]); + EXPECT_EQ(ConditionState::kFalse, conditionCache[1]); + EXPECT_EQ(ConditionState::kFalse, conditionCache[2]); + EXPECT_EQ(ConditionState::kFalse, conditionCache[3]); + EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]); + + EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition); + EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition); + EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition); + EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition); +} + TEST(MetricsManagerTest, TestGoodConfig) { UidMap uidMap; sp<StatsPullerManager> pullerManager = new StatsPullerManager(); diff --git a/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp b/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp index 6529d65a5825..1d501fd5a87c 100644 --- a/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp +++ b/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp @@ -24,6 +24,7 @@ using namespace android::os::statsd; using std::vector; #ifdef __ANDROID__ + TEST(ConditionTrackerTest, TestUnknownCondition) { LogicalOperation operation = LogicalOperation::AND; diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp index 86e24fb0c80b..07b5311b1207 100644 --- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp +++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp @@ -112,6 +112,114 @@ std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey( return outputKeyMap; } +TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueFalse) { + SimplePredicate simplePredicate; + simplePredicate.set_start(StringToId("SCREEN_TURNED_ON")); + simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF")); + simplePredicate.set_count_nesting(false); + simplePredicate.set_initial_value(SimplePredicate_InitialValue_FALSE); + + unordered_map<int64_t, int> trackerNameIndexMap; + trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0; + trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1; + + SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), + 0 /*tracker index*/, simplePredicate, + trackerNameIndexMap); + + ConditionKey queryKey; + vector<sp<ConditionTracker>> allPredicates; + vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); + + // Check that initial condition is false. + conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache); + EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); + + vector<MatchingState> matcherState; + vector<bool> changedCache(1, false); + + // Matched stop event. + // Check that condition is still false. + unique_ptr<LogEvent> screenOffEvent = + CreateScreenStateChangedEvent(/*timestamp=*/50, android::view::DISPLAY_STATE_OFF); + matcherState.clear(); + matcherState.push_back(MatchingState::kNotMatched); // On matcher not matched + matcherState.push_back(MatchingState::kMatched); // Off matcher matched + conditionCache[0] = ConditionState::kNotEvaluated; + conditionTracker.evaluateCondition(*screenOffEvent, matcherState, allPredicates, conditionCache, + changedCache); + EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); + EXPECT_FALSE(changedCache[0]); + + // Matched start event. + // Check that condition has changed to true. + unique_ptr<LogEvent> screenOnEvent = + CreateScreenStateChangedEvent(/*timestamp=*/100, android::view::DISPLAY_STATE_ON); + matcherState.clear(); + matcherState.push_back(MatchingState::kMatched); // On matcher matched + matcherState.push_back(MatchingState::kNotMatched); // Off matcher not matched + conditionCache[0] = ConditionState::kNotEvaluated; + changedCache[0] = false; + conditionTracker.evaluateCondition(*screenOnEvent, matcherState, allPredicates, conditionCache, + changedCache); + EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); + EXPECT_TRUE(changedCache[0]); +} + +TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueUnknown) { + SimplePredicate simplePredicate; + simplePredicate.set_start(StringToId("SCREEN_TURNED_ON")); + simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF")); + simplePredicate.set_count_nesting(false); + simplePredicate.set_initial_value(SimplePredicate_InitialValue_UNKNOWN); + + unordered_map<int64_t, int> trackerNameIndexMap; + trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0; + trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1; + + SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), + 0 /*tracker index*/, simplePredicate, + trackerNameIndexMap); + + ConditionKey queryKey; + vector<sp<ConditionTracker>> allPredicates; + vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); + + // Check that initial condition is unknown. + conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache); + EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]); + + vector<MatchingState> matcherState; + vector<bool> changedCache(1, false); + + // Matched stop event. + // Check that condition is changed to false. + unique_ptr<LogEvent> screenOffEvent = + CreateScreenStateChangedEvent(/*timestamp=*/50, android::view::DISPLAY_STATE_OFF); + matcherState.clear(); + matcherState.push_back(MatchingState::kNotMatched); // On matcher not matched + matcherState.push_back(MatchingState::kMatched); // Off matcher matched + conditionCache[0] = ConditionState::kNotEvaluated; + conditionTracker.evaluateCondition(*screenOffEvent, matcherState, allPredicates, conditionCache, + changedCache); + EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); + EXPECT_TRUE(changedCache[0]); + + // Matched start event. + // Check that condition has changed to true. + unique_ptr<LogEvent> screenOnEvent = + CreateScreenStateChangedEvent(/*timestamp=*/100, android::view::DISPLAY_STATE_ON); + matcherState.clear(); + matcherState.push_back(MatchingState::kMatched); // On matcher matched + matcherState.push_back(MatchingState::kNotMatched); // Off matcher not matched + conditionCache[0] = ConditionState::kNotEvaluated; + changedCache[0] = false; + conditionTracker.evaluateCondition(*screenOnEvent, matcherState, allPredicates, conditionCache, + changedCache); + EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); + EXPECT_TRUE(changedCache[0]); +} + TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) { SimplePredicate simplePredicate; simplePredicate.set_start(StringToId("SCREEN_TURNED_ON")); diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp index 74ecaac0f9e3..bb8e7bfd90f4 100644 --- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp @@ -74,8 +74,8 @@ TEST(CountMetricProducerTest, TestFirstBucket) { metric.set_bucket(ONE_MINUTE); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5, - 600 * NS_PER_SEC + NS_PER_SEC / 2); + CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2); EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(10, countProducer.mCurrentBucketNum); EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs()); @@ -94,8 +94,8 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - bucketStartTimeNs, bucketStartTimeNs); + CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, bucketStartTimeNs, bucketStartTimeNs); // 2 events in bucket 1. LogEvent event1(/*uid=*/0, /*pid=*/0); @@ -157,8 +157,8 @@ TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs, - bucketStartTimeNs); + CountMetricProducer countProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, + bucketStartTimeNs, bucketStartTimeNs); countProducer.onConditionChanged(true, bucketStartTimeNs); @@ -220,12 +220,14 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) { getMockedDimensionKey(conditionTagId, 2, "222")}; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); + EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse)); EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue)); - CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard, - bucketStartTimeNs, bucketStartTimeNs); + CountMetricProducer countProducer(kConfigKey, metric, 0 /*condition tracker index*/, + {ConditionState::kUnknown}, wizard, bucketStartTimeNs, + bucketStartTimeNs); countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1); countProducer.flushIfNeededLocked(bucketStartTimeNs + 1); @@ -261,7 +263,8 @@ TEST_P(CountMetricProducerTest_PartialBucket, TestSplitInCurrentBucket) { alert.set_trigger_if_sum_gt(2); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard, + + CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, {}, wizard, bucketStartTimeNs, bucketStartTimeNs); sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor); @@ -327,7 +330,8 @@ TEST_P(CountMetricProducerTest_PartialBucket, TestSplitInNextBucket) { metric.set_bucket(ONE_MINUTE); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard, + + CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, {}, wizard, bucketStartTimeNs, bucketStartTimeNs); // Bucket is flushed yet. @@ -391,8 +395,9 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) { metric.set_bucket(ONE_MINUTE); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - bucketStartTimeNs, bucketStartTimeNs); + + CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, bucketStartTimeNs, bucketStartTimeNs); sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor); @@ -453,8 +458,8 @@ TEST(CountMetricProducerTest, TestOneWeekTimeUnit) { int64_t oneDayNs = 24 * 60 * 60 * 1e9; int64_t fiveWeeksNs = 5 * 7 * oneDayNs; - CountMetricProducer countProducer( - kConfigKey, metric, -1 /* meaning no condition */, wizard, oneDayNs, fiveWeeksNs); + CountMetricProducer countProducer(kConfigKey, metric, -1 /* meaning no condition */, {}, wizard, + oneDayNs, fiveWeeksNs); int64_t fiveWeeksOneDayNs = fiveWeeksNs + oneDayNs; diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp index ddda71db4bd4..05cfa37b0ee1 100644 --- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp @@ -70,9 +70,11 @@ TEST(DurationMetricTrackerTest, TestFirstBucket) { metric.set_aggregation_type(DurationMetric_AggregationType_SUM); FieldMatcher dimensions; - DurationMetricProducer durationProducer( - kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */, - 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, 5, 600 * NS_PER_SEC + NS_PER_SEC/2); + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, {}, + 1 /* start index */, 2 /* stop index */, + 3 /* stop_all index */, false /*nesting*/, wizard, + dimensions, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2); EXPECT_EQ(600500000000, durationProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(10, durationProducer.mCurrentBucketNum); @@ -96,7 +98,8 @@ TEST(DurationMetricTrackerTest, TestNoCondition) { makeLogEvent(&event2, bucketStartTimeNs + bucketSizeNs + 2, tagId); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); @@ -138,10 +141,11 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) { makeLogEvent(&event4, bucketStartTimeNs + bucketSizeNs + 3, tagId); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, 0 /* condition index */, - 1 /* start index */, 2 /* stop index */, - 3 /* stop_all index */, false /*nesting*/, wizard, - dimensions, bucketStartTimeNs, bucketStartTimeNs); + + DurationMetricProducer durationProducer( + kConfigKey, metric, 0 /* condition index */, {ConditionState::kUnknown}, + 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, + wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); durationProducer.mCondition = ConditionState::kFalse; EXPECT_FALSE(durationProducer.mCondition); @@ -187,10 +191,11 @@ TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) { makeLogEvent(&event4, bucketStartTimeNs + bucketSizeNs + 3, tagId); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, 0 /* condition index */, - 1 /* start index */, 2 /* stop index */, - 3 /* stop_all index */, false /*nesting*/, wizard, - dimensions, bucketStartTimeNs, bucketStartTimeNs); + + DurationMetricProducer durationProducer( + kConfigKey, metric, 0 /* condition index */, {ConditionState::kUnknown}, + 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, + wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition); EXPECT_FALSE(durationProducer.isConditionSliced()); @@ -232,7 +237,8 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDuration) { metric.set_aggregation_type(DurationMetric_AggregationType_SUM); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); @@ -294,7 +300,8 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDurationWithSplitInFollo metric.set_aggregation_type(DurationMetric_AggregationType_SUM); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); @@ -357,7 +364,8 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDurationAnomaly) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); @@ -402,7 +410,8 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestMaxDuration) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); @@ -455,7 +464,8 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextB sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); FieldMatcher dimensions; - DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, + + DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs); diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp index 5bae3648bd80..dfbb9da568b0 100644 --- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp @@ -65,8 +65,8 @@ TEST(EventMetricProducerTest, TestNoCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - bucketStartTimeNs); + EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, bucketStartTimeNs); eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1); eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2); @@ -101,7 +101,8 @@ TEST(EventMetricProducerTest, TestEventsWithNonSlicedCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs); + EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/, + {ConditionState::kUnknown}, wizard, bucketStartTimeNs); eventProducer.onConditionChanged(true /*condition*/, bucketStartTimeNs); eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1); @@ -155,7 +156,8 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) { // Condition is true for second event. EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue)); - EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs); + EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/, + {ConditionState::kUnknown}, wizard, bucketStartTimeNs); eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1); eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index cc5f45922d45..5997bedcdf2d 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -104,10 +104,9 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) { // statsd started long ago. // The metric starts in the middle of the bucket - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, - pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, -1, -1, + tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager); gaugeProducer.prepareFirstBucket(); EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs); @@ -147,9 +146,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); vector<shared_ptr<LogEvent>> allData; @@ -225,8 +224,8 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) { new EventMatcherWizard({new SimpleLogMatchingTracker( atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); @@ -308,7 +307,6 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) { sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({new SimpleLogMatchingTracker( atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); @@ -322,9 +320,9 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) { return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); vector<shared_ptr<LogEvent>> allData; @@ -393,9 +391,9 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) { EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) .WillOnce(Return(false)); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); vector<shared_ptr<LogEvent>> allData; @@ -450,7 +448,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, + GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/, + {ConditionState::kUnknown}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); @@ -536,7 +535,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, + GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/, + {ConditionState::kUnknown}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); @@ -584,9 +584,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { new EventMatcherWizard({new SimpleLogMatchingTracker( atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); Alert alert; @@ -683,9 +683,10 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) { .WillOnce(Return(true)); int triggerId = 5; - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, triggerId, - tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, + pullerManager); gaugeProducer.prepareFirstBucket(); ASSERT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size()); @@ -761,9 +762,10 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) { .WillOnce(Return(true)); int triggerId = 5; - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, triggerId, - tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, + pullerManager); gaugeProducer.prepareFirstBucket(); LogEvent triggerEvent(/*uid=*/0, /*pid=*/0); @@ -823,9 +825,10 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) { })); int triggerId = 5; - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, triggerId, - tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, + pullerManager); gaugeProducer.prepareFirstBucket(); LogEvent triggerEvent(/*uid=*/0, /*pid=*/0); diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 52eb7409aa5d..1bcc35d99d18 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -111,37 +111,17 @@ public: EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)) .WillRepeatedly(Return()); - sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( - kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, - eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + sp<ValueMetricProducer> valueProducer = + new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer->prepareFirstBucket(); return valueProducer; } static sp<ValueMetricProducer> createValueProducerWithCondition( - sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) { - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)) - .WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)) - .WillRepeatedly(Return()); - - sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( - kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); - valueProducer->prepareFirstBucket(); - valueProducer->mCondition = ConditionState::kFalse; - return valueProducer; - } - - static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition( - sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) { + sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric, + ConditionState conditionAfterFirstBucketPrepared) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); @@ -155,9 +135,11 @@ public: .WillRepeatedly(Return()); sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( - kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + kConfigKey, metric, 0 /*condition index*/, {ConditionState::kUnknown}, wizard, + logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, + bucketStartTimeNs, pullerManager); valueProducer->prepareFirstBucket(); + valueProducer->mCondition = conditionAfterFirstBucketPrepared; return valueProducer; } @@ -176,8 +158,9 @@ public: .WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)) .WillRepeatedly(Return()); + sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( - kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex, + kConfigKey, metric, -1 /* no condition */, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap); valueProducer->prepareFirstBucket(); @@ -232,9 +215,9 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) { // statsd started long ago. // The metric starts in the middle of the bucket - ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase, - 22, pullerManager); + ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, -1, + startTimeBase, 22, pullerManager); valueProducer.prepareFirstBucket(); EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10)); @@ -262,8 +245,8 @@ TEST(ValueMetricProducerTest, TestFirstBucket) { // statsd started long ago. // The metric starts in the middle of the bucket - ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, -1, 5, + ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, -1, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager); valueProducer.prepareFirstBucket(); @@ -427,7 +410,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { })); sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( - kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, + kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer->prepareFirstBucket(); @@ -629,7 +612,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); @@ -689,7 +673,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) { atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -762,7 +747,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) { data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120)); return true; })); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -813,7 +799,8 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) .WillOnce(Return(true)); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -851,7 +838,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse return true; })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 1); @@ -875,6 +863,7 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse {bucketStartTimeNs}, {partialBucketSplitTimeNs}); EXPECT_FALSE(valueProducer->mCondition); } + TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); @@ -887,7 +876,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -931,9 +920,9 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, - eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, - pullerManager); + ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, + logEventMatcherIndex, eventMatcherWizard, -1, + bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); valueProducer.mCondition = ConditionState::kFalse; @@ -1001,9 +990,11 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + + ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, + -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs, + pullerManager); valueProducer.prepareFirstBucket(); sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor); @@ -1158,7 +1149,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) { return true; })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); @@ -1229,7 +1221,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); @@ -1300,7 +1293,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -1344,7 +1337,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -1387,7 +1380,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -1435,7 +1428,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -1479,7 +1472,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -1551,7 +1544,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -1944,7 +1937,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); // has one slice @@ -1979,7 +1973,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) { .WillOnce(Return(false)); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); @@ -2023,7 +2018,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Don't directly set mCondition; the real code never does that. Go through regular code path // to avoid unexpected behaviors. @@ -2057,9 +2053,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Max delay is set to 0 so pull will exceed max delay. valueProducer->onConditionChanged(true, bucketStartTimeNs + 1); @@ -2080,9 +2075,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return()); - ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, - eventMatcherWizard, tagId, bucket2StartTimeNs, - bucket2StartTimeNs, pullerManager); + ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, + logEventMatcherIndex, eventMatcherWizard, tagId, + bucket2StartTimeNs, bucket2StartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); valueProducer.mCondition = ConditionState::kFalse; @@ -2105,9 +2100,8 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->mHasGlobalBase = false; valueProducer->onConditionChanged(true, bucketStartTimeNs + 1); @@ -2142,9 +2136,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - - valueProducer->mCondition = ConditionState::kTrue; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kTrue); // Bucket start. vector<shared_ptr<LogEvent>> allData; @@ -2218,8 +2211,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 2); EXPECT_EQ(true, valueProducer->mCurrentBucketIsSkipped); @@ -2283,9 +2276,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - - valueProducer->mCondition = ConditionState::kTrue; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kTrue); // Bucket start. vector<shared_ptr<LogEvent>> allData; @@ -2363,9 +2355,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - - valueProducer->mCondition = ConditionState::kTrue; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kTrue); // Bucket start. vector<shared_ptr<LogEvent>> allData; @@ -2468,7 +2459,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); @@ -2518,7 +2510,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); valueProducer->onConditionChanged(false, bucketStartTimeNs + 11); @@ -2566,7 +2559,8 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); @@ -2673,8 +2667,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - valueProducer->mCondition = ConditionState::kUnknown; + ValueMetricProducerTestHelper::createValueProducerWithCondition( + pullerManager, metric, ConditionState::kUnknown); valueProducer->onConditionChanged(false, bucketStartTimeNs); ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); @@ -2814,7 +2808,8 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); valueProducer->onConditionChanged(false, bucketStartTimeNs + 10); @@ -2866,7 +2861,8 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10); vector<shared_ptr<LogEvent>> allData; @@ -2911,7 +2907,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) { return true; })); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -2949,7 +2945,7 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { return true; })); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -3002,7 +2998,7 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) { return true; })); - ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); valueProducer.prepareFirstBucket(); @@ -3058,8 +3054,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges return true; })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); valueProducer->onConditionChanged(false, bucketStartTimeNs + 50); @@ -3099,8 +3095,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) { return true; })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); @@ -3124,8 +3120,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Now the alarm is delivered. Condition is off though. vector<shared_ptr<LogEvent>> allData; @@ -3152,8 +3148,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) { })) .WillOnce(Return(false)); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); - valueProducer->mCondition = ConditionState::kFalse; + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); valueProducer->onConditionChanged(false, bucketStartTimeNs + 50); @@ -3191,7 +3187,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequeste })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 20); @@ -3236,7 +3233,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWron })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 50); @@ -3298,7 +3296,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWro })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 50); @@ -3363,8 +3362,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager, - metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition( + pullerManager, metric, ConditionState::kUnknown); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 50); @@ -3413,7 +3412,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) { .WillOnce(Return(false)); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 50); @@ -3468,7 +3468,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSki })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); @@ -3542,7 +3543,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); @@ -3579,7 +3581,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenDataUnavailable) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition( + pullerManager, metric, ConditionState::kUnknown); // Check dump report. ProtoOutputStream output; @@ -3632,7 +3635,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenForceBucketSplitBefor })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric, + ConditionState::kFalse); // Condition changed event int64_t conditionChangeTimeNs = bucketStartTimeNs + 10; @@ -3687,8 +3691,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager, - metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition( + pullerManager, metric, ConditionState::kUnknown); // Condition change event. valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); @@ -3756,8 +3760,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) { })); sp<ValueMetricProducer> valueProducer = - ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager, - metric); + ValueMetricProducerTestHelper::createValueProducerWithCondition( + pullerManager, metric, ConditionState::kUnknown); // First condition change event causes guardrail to be reached. valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 87fc8fe392f0..6c10682adc0e 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5568,7 +5568,7 @@ public class Activity extends ContextThemeWrapper options = transferSpringboardActivityOptions(options); String resolvedType = null; if (fillInIntent != null) { - fillInIntent.migrateExtraStreamToClipData(); + fillInIntent.migrateExtraStreamToClipData(this); fillInIntent.prepareToLeaveProcess(this); resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); } @@ -5823,7 +5823,7 @@ public class Activity extends ContextThemeWrapper if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(this); intent.prepareToLeaveProcess(this); result = ActivityTaskManager.getService() .startActivity(mMainThread.getApplicationThread(), getBasePackageName(), @@ -5894,7 +5894,7 @@ public class Activity extends ContextThemeWrapper @Nullable Bundle options) { if (mParent == null) { try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(this); intent.prepareToLeaveProcess(this); return ActivityTaskManager.getService() .startNextMatchingActivity(mToken, intent, options); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 48160e475d50..86a3579effe1 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1087,7 +1087,7 @@ class ContextImpl extends Context { try { String resolvedType = null; if (fillInIntent != null) { - fillInIntent.migrateExtraStreamToClipData(); + fillInIntent.migrateExtraStreamToClipData(this); fillInIntent.prepareToLeaveProcess(this); resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); } diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index e233adeb3f65..721525d9af9d 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1718,7 +1718,7 @@ public class Instrumentation { } } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); int result = ActivityTaskManager.getService().startActivity(whoThread, who.getBasePackageName(), who.getAttributionTag(), intent, @@ -1788,7 +1788,7 @@ public class Instrumentation { try { String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { - intents[i].migrateExtraStreamToClipData(); + intents[i].migrateExtraStreamToClipData(who); intents[i].prepareToLeaveProcess(who); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver()); } @@ -1857,7 +1857,7 @@ public class Instrumentation { } } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); int result = ActivityTaskManager.getService().startActivity(whoThread, who.getBasePackageName(), who.getAttributionTag(), intent, @@ -1924,7 +1924,7 @@ public class Instrumentation { } } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); int result = ActivityTaskManager.getService().startActivityAsUser(whoThread, who.getBasePackageName(), who.getAttributionTag(), intent, @@ -1970,7 +1970,7 @@ public class Instrumentation { } } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); int result = ActivityTaskManager.getService() .startActivityAsCaller(whoThread, who.getBasePackageName(), intent, @@ -2017,7 +2017,7 @@ public class Instrumentation { } } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(), who.getAttributionTag(), intent, diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 792f840638a9..cd352e141994 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -351,7 +351,7 @@ public final class PendingIntent implements Parcelable { String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(context); intent.prepareToLeaveProcess(context); IIntentSender target = ActivityManager.getService().getIntentSenderWithFeature( @@ -377,7 +377,7 @@ public final class PendingIntent implements Parcelable { String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(context); intent.prepareToLeaveProcess(context); IIntentSender target = ActivityManager.getService().getIntentSenderWithFeature( @@ -491,7 +491,7 @@ public final class PendingIntent implements Parcelable { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { - intents[i].migrateExtraStreamToClipData(); + intents[i].migrateExtraStreamToClipData(context); intents[i].prepareToLeaveProcess(context); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); } @@ -517,7 +517,7 @@ public final class PendingIntent implements Parcelable { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { - intents[i].migrateExtraStreamToClipData(); + intents[i].migrateExtraStreamToClipData(context); intents[i].prepareToLeaveProcess(context); resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index baaf8f76797a..e331471a33db 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -11272,6 +11272,19 @@ public class Intent implements Parcelable, Cloneable { * @hide */ public boolean migrateExtraStreamToClipData() { + return migrateExtraStreamToClipData(AppGlobals.getInitialApplication()); + } + + /** + * Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and + * {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}. Also inspects nested + * intents in {@link #ACTION_CHOOSER}. + * + * @param context app context + * @return Whether any contents were migrated. + * @hide + */ + public boolean migrateExtraStreamToClipData(Context context) { // Refuse to touch if extras already parcelled if (mExtras != null && mExtras.isParcelled()) return false; @@ -11289,7 +11302,7 @@ public class Intent implements Parcelable, Cloneable { try { final Intent intent = getParcelableExtra(EXTRA_INTENT); if (intent != null) { - migrated |= intent.migrateExtraStreamToClipData(); + migrated |= intent.migrateExtraStreamToClipData(context); } } catch (ClassCastException e) { } @@ -11299,7 +11312,7 @@ public class Intent implements Parcelable, Cloneable { for (int i = 0; i < intents.length; i++) { final Intent intent = (Intent) intents[i]; if (intent != null) { - migrated |= intent.migrateExtraStreamToClipData(); + migrated |= intent.migrateExtraStreamToClipData(context); } } } @@ -11362,13 +11375,17 @@ public class Intent implements Parcelable, Cloneable { } catch (ClassCastException e) { } } else if (isImageCaptureIntent()) { - final Uri output; + Uri output; try { output = getParcelableExtra(MediaStore.EXTRA_OUTPUT); } catch (ClassCastException e) { return false; } + if (output != null) { + output = maybeConvertFileToContentUri(context, output); + putExtra(MediaStore.EXTRA_OUTPUT, output); + setClipData(ClipData.newRawUri("", output)); addFlags(FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION); return true; @@ -11378,6 +11395,23 @@ public class Intent implements Parcelable, Cloneable { return false; } + private Uri maybeConvertFileToContentUri(Context context, Uri uri) { + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme()) + && context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.R) { + File file = new File(uri.getPath()); + try { + if (!file.exists()) file.createNewFile(); + uri = MediaStore.scanFile(context.getContentResolver(), new File(uri.getPath())); + if (uri != null) { + return uri; + } + } catch (IOException e) { + Log.e(TAG, "Ignoring failure to create file " + file, e); + } + } + return uri; + } + /** * Convert the dock state to a human readable format. * @hide diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index b1f88693d9c0..bd02210259b8 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -245,6 +245,13 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { public float minAspectRatio; /** + * Indicates that the activity works well with size changes like display changing size. + * + * @hide + */ + public boolean supportsSizeChanges; + + /** * Name of the VrListenerService component to run for this activity. * @see android.R.attr#enableVrMode * @hide @@ -1013,6 +1020,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { colorMode = orig.colorMode; maxAspectRatio = orig.maxAspectRatio; minAspectRatio = orig.minAspectRatio; + supportsSizeChanges = orig.supportsSizeChanges; } /** @@ -1188,6 +1196,9 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { if (minAspectRatio != 0) { pw.println(prefix + "minAspectRatio=" + minAspectRatio); } + if (supportsSizeChanges) { + pw.println(prefix + "supportsSizeChanges=true"); + } super.dumpBack(pw, prefix, dumpFlags); } @@ -1232,6 +1243,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { dest.writeInt(colorMode); dest.writeFloat(maxAspectRatio); dest.writeFloat(minAspectRatio); + dest.writeBoolean(supportsSizeChanges); } /** @@ -1350,6 +1362,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { colorMode = source.readInt(); maxAspectRatio = source.readFloat(); minAspectRatio = source.readFloat(); + supportsSizeChanges = source.readBoolean(); } /** diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 0d8618fe7e86..c8dd4d9d9d51 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -207,6 +207,7 @@ public class PackageParser { public static final String TAG_USES_SPLIT = "uses-split"; public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect"; + public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes"; public static final String METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY = "android.activity_window_layout_affinity"; @@ -3897,6 +3898,7 @@ public class PackageParser { // every activity info has had a chance to set it from its attributes. setMaxAspectRatio(owner); setMinAspectRatio(owner); + setSupportsSizeChanges(owner); if (hasDomainURLs(owner)) { owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS; @@ -4694,6 +4696,18 @@ public class PackageParser { } } + private void setSupportsSizeChanges(Package owner) { + final boolean supportsSizeChanges = owner.mAppMetaData != null + && owner.mAppMetaData.getBoolean(METADATA_SUPPORTS_SIZE_CHANGES, false); + + for (Activity activity : owner.activities) { + if (supportsSizeChanges || (activity.metaData != null + && activity.metaData.getBoolean(METADATA_SUPPORTS_SIZE_CHANGES, false))) { + activity.info.supportsSizeChanges = true; + } + } + } + /** * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml. * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from @@ -4863,6 +4877,7 @@ public class PackageParser { info.resizeMode = target.info.resizeMode; info.maxAspectRatio = target.info.maxAspectRatio; info.minAspectRatio = target.info.minAspectRatio; + info.supportsSizeChanges = target.info.supportsSizeChanges; info.requestedVrComponent = target.info.requestedVrComponent; info.directBootAware = target.info.directBootAware; diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java index 216b3bb5de8e..e4507483c08f 100644 --- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java +++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java @@ -445,6 +445,7 @@ public class PackageInfoWithoutStateUtils { ai.maxAspectRatio = maxAspectRatio != null ? maxAspectRatio : 0f; Float minAspectRatio = a.getMinAspectRatio(); ai.minAspectRatio = minAspectRatio != null ? minAspectRatio : 0f; + ai.supportsSizeChanges = a.getSupportsSizeChanges(); ai.requestedVrComponent = a.getRequestedVrComponent(); ai.rotationAnimation = a.getRotationAnimation(); ai.colorMode = a.getColorMode(); diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 5a7947503d5c..317107829623 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -1912,6 +1912,7 @@ public class ParsingPackageUtils { // every activity info has had a chance to set it from its attributes. setMaxAspectRatio(pkg); setMinAspectRatio(pkg); + setSupportsSizeChanges(pkg); pkg.setHasDomainUrls(hasDomainURLs(pkg)); @@ -2366,6 +2367,23 @@ public class ParsingPackageUtils { } } + private void setSupportsSizeChanges(ParsingPackage pkg) { + final Bundle appMetaData = pkg.getMetaData(); + final boolean supportsSizeChanges = appMetaData != null + && appMetaData.getBoolean(PackageParser.METADATA_SUPPORTS_SIZE_CHANGES, false); + + List<ParsedActivity> activities = pkg.getActivities(); + int activitiesSize = activities.size(); + for (int index = 0; index < activitiesSize; index++) { + ParsedActivity activity = activities.get(index); + if (supportsSizeChanges || (activity.getMetaData() != null + && activity.getMetaData().getBoolean( + PackageParser.METADATA_SUPPORTS_SIZE_CHANGES, false))) { + activity.setSupportsSizeChanges(true); + } + } + } + private static ParseResult<ParsingPackage> parseOverlay(ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser) { TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestResourceOverlay); diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java index 4c93d0950388..19150283d71e 100644 --- a/core/java/android/content/pm/parsing/component/ParsedActivity.java +++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java @@ -73,6 +73,8 @@ public class ParsedActivity extends ParsedMainComponent { @Nullable private Float minAspectRatio; + private boolean supportsSizeChanges; + @Nullable String requestedVrComponent; int rotationAnimation = -1; @@ -101,6 +103,7 @@ public class ParsedActivity extends ParsedMainComponent { this.resizeMode = other.resizeMode; this.maxAspectRatio = other.maxAspectRatio; this.minAspectRatio = other.minAspectRatio; + this.supportsSizeChanges = other.supportsSizeChanges; this.requestedVrComponent = other.requestedVrComponent; this.rotationAnimation = other.rotationAnimation; this.colorMode = other.colorMode; @@ -165,6 +168,7 @@ public class ParsedActivity extends ParsedMainComponent { alias.resizeMode = target.resizeMode; alias.maxAspectRatio = target.maxAspectRatio; alias.minAspectRatio = target.minAspectRatio; + alias.supportsSizeChanges = target.supportsSizeChanges; alias.requestedVrComponent = target.requestedVrComponent; alias.directBootAware = target.directBootAware; alias.setProcessName(target.getProcessName()); @@ -217,6 +221,11 @@ public class ParsedActivity extends ParsedMainComponent { return this; } + public ParsedActivity setSupportsSizeChanges(boolean supportsSizeChanges) { + this.supportsSizeChanges = supportsSizeChanges; + return this; + } + public ParsedActivity setFlags(int flags) { this.flags = flags; return this; @@ -279,6 +288,7 @@ public class ParsedActivity extends ParsedMainComponent { dest.writeInt(this.resizeMode); dest.writeValue(this.maxAspectRatio); dest.writeValue(this.minAspectRatio); + dest.writeBoolean(this.supportsSizeChanges); dest.writeString(this.requestedVrComponent); dest.writeInt(this.rotationAnimation); dest.writeInt(this.colorMode); @@ -315,6 +325,7 @@ public class ParsedActivity extends ParsedMainComponent { this.resizeMode = in.readInt(); this.maxAspectRatio = (Float) in.readValue(Float.class.getClassLoader()); this.minAspectRatio = (Float) in.readValue(Float.class.getClassLoader()); + this.supportsSizeChanges = in.readBoolean(); this.requestedVrComponent = in.readString(); this.rotationAnimation = in.readInt(); this.colorMode = in.readInt(); @@ -414,6 +425,10 @@ public class ParsedActivity extends ParsedMainComponent { return minAspectRatio; } + public boolean getSupportsSizeChanges() { + return supportsSizeChanges; + } + @Nullable public String getRequestedVrComponent() { return requestedVrComponent; diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl index b4ebed704441..c1dd20d66d53 100644 --- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl +++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl @@ -57,5 +57,5 @@ interface IBiometricAuthenticator { void setActiveUser(int uid); // Gets the authenticator ID representing the current set of enrolled templates - long getAuthenticatorId(); + long getAuthenticatorId(int callingUserId); } diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index 10295db38120..07f88c2fbea6 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -65,5 +65,5 @@ interface IBiometricService { // Get a list of AuthenticatorIDs for authenticators which have enrolled templates and meet // the requirements for integrating with Keystore. The AuthenticatorID are known in Keystore // land as SIDs, and are used during key generation. - long[] getAuthenticatorIds(); + long[] getAuthenticatorIds(int callingUserId); } diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 03937e0276e6..e2ab529d1e86 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -85,7 +85,7 @@ interface IFaceService { // long getHardwareDevice(int i); // Gets the authenticator ID for face - long getAuthenticatorId(); + long getAuthenticatorId(int callingUserId); // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) void resetLockout(in byte [] token); diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 2507c840d0e9..c5c375543adc 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -89,7 +89,7 @@ interface IFingerprintService { // long getHardwareDevice(int i); // Gets the authenticator ID for fingerprint - long getAuthenticatorId(); + long getAuthenticatorId(int callingUserId); // Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password) void resetTimeout(in byte [] cryptoToken); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 9ded22fb70c6..a3fd60e9d3b0 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -679,13 +679,14 @@ public final class NetworkCapabilities implements Parcelable { */ public void restrictCapabilitesForTestNetwork(int creatorUid) { final long originalCapabilities = mNetworkCapabilities; + final long originalTransportTypes = mTransportTypes; final NetworkSpecifier originalSpecifier = mNetworkSpecifier; final int originalSignalStrength = mSignalStrength; final int originalOwnerUid = getOwnerUid(); final int[] originalAdministratorUids = getAdministratorUids(); clearAll(); - // Reset the transports to only contain TRANSPORT_TEST. - mTransportTypes = (1 << TRANSPORT_TEST); + mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS) + | (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; mSignalStrength = originalSignalStrength; @@ -787,6 +788,13 @@ public final class NetworkCapabilities implements Parcelable { }; /** + * Allowed transports on a test network, in addition to TRANSPORT_TEST. + */ + private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST + // Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces + | 1 << TRANSPORT_ETHERNET; + + /** * Adds the given transport type to this {@code NetworkCapability} instance. * Multiple transports may be applied. Note that when searching * for a network to satisfy a request, any listed in the request will satisfy the request. diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java index 92574968e965..74b814ea4159 100644 --- a/core/java/android/os/AppZygote.java +++ b/core/java/android/os/AppZygote.java @@ -92,10 +92,9 @@ public class AppZygote { @GuardedBy("mLock") private void stopZygoteLocked() { if (mZygote != null) { - // Close the connection and kill the zygote process. This will not cause - // child processes to be killed by itself. mZygote.close(); - Process.killProcess(mZygote.getPid()); + // use killProcessGroup() here, so we kill all untracked children as well. + Process.killProcessGroup(mZygoteUid, mZygote.getPid()); mZygote = null; } } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 66b8cabe03c3..4ca48cb3e57c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -56,6 +56,7 @@ import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.content.res.ObbInfo; import android.content.res.ObbScanner; +import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Environment; @@ -1201,7 +1202,19 @@ public class StorageManager { * {@link MediaStore} item. */ public @NonNull StorageVolume getStorageVolume(@NonNull Uri uri) { - final String volumeName = MediaStore.getVolumeName(uri); + String volumeName = MediaStore.getVolumeName(uri); + + // When Uri is pointing at a synthetic volume, we're willing to query to + // resolve the actual volume name + if (Objects.equals(volumeName, MediaStore.VOLUME_EXTERNAL)) { + try (Cursor c = mContext.getContentResolver().query(uri, + new String[] { MediaStore.MediaColumns.VOLUME_NAME }, null, null)) { + if (c.moveToFirst()) { + volumeName = c.getString(0); + } + } + } + switch (volumeName) { case MediaStore.VOLUME_EXTERNAL_PRIMARY: return getPrimaryStorageVolume(); diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 4a0dd870f797..0341b6d96b29 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -1311,7 +1311,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall throw new IllegalStateException("Can't call before onCreate()"); } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(mContext); intent.prepareToLeaveProcess(mContext); int res = mSystemService.startVoiceActivity(mToken, intent, intent.resolveType(mContext.getContentResolver()), @@ -1340,7 +1340,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall throw new IllegalStateException("Can't call before onCreate()"); } try { - intent.migrateExtraStreamToClipData(); + intent.migrateExtraStreamToClipData(mContext); intent.prepareToLeaveProcess(mContext); int res = mSystemService.startAssistantActivity(mToken, intent, intent.resolveType(mContext.getContentResolver()), diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index d12ca73599f3..4e07a5f58de4 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -195,7 +195,10 @@ public class Surface implements Parcelable { // From native_window.h. Keep these in sync. /** - * There are no inherent restrictions on the frame rate of this surface. + * There are no inherent restrictions on the frame rate of this surface. When the + * system selects a frame rate other than what the app requested, the app will be able + * to run at the system frame rate without requiring pull down. This value should be + * used when displaying game content, UIs, and anything that isn't video. */ public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; @@ -205,7 +208,7 @@ public class Surface implements Parcelable { * other than what the app requested, the app will need to do pull down or use some * other technique to adapt to the system's frame rate. The user experience is likely * to be worse (e.g. more frame stuttering) than it would be if the system had chosen - * the app's requested frame rate. + * the app's requested frame rate. This value should be used for video content. */ public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 9109f50247e0..6f73e8985a8a 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -323,6 +323,14 @@ public final class SurfaceControl implements Parcelable { public static final int CURSOR_WINDOW = 0x00002000; /** + * Surface creation flag: Indicates the effect layer will not have a color fill on + * creation. + * + * @hide + */ + public static final int NO_COLOR_FILL = 0x00004000; + + /** * Surface creation flag: Creates a normal surface. * This is the default. * @@ -577,7 +585,7 @@ public final class SurfaceControl implements Parcelable { throw new IllegalStateException( "width and height must be positive or unset"); } - if ((mWidth > 0 || mHeight > 0) && (isColorLayerSet() || isContainerLayerSet())) { + if ((mWidth > 0 || mHeight > 0) && (isEffectLayer() || isContainerLayer())) { throw new IllegalStateException( "Only buffer layers can set a valid buffer size."); } @@ -749,10 +757,27 @@ public final class SurfaceControl implements Parcelable { } /** - * Indicate whether a 'ColorLayer' is to be constructed. + * Indicate whether an 'EffectLayer' is to be constructed. + * + * An effect layer behaves like a container layer by default but it can support + * color fill, shadows and/or blur. These layers will not have an associated buffer. + * When created, this layer has no effects set and will be transparent but the caller + * can render an effect by calling: + * - {@link Transaction#setColor(SurfaceControl, float[])} + * - {@link Transaction#setBackgroundBlurRadius(SurfaceControl, int)} + * - {@link Transaction#setShadowRadius(SurfaceControl, float)} * - * Color layers will not have an associated BufferQueue and will instead always render a - * solid color (that is, solid before plane alpha). Currently that color is black. + * @hide + */ + public Builder setEffectLayer() { + mFlags |= NO_COLOR_FILL; + unsetBufferSize(); + return setFlags(FX_SURFACE_EFFECT, FX_SURFACE_MASK); + } + + /** + * A convenience function to create an effect layer with a default color fill + * applied to it. Currently that color is black. * * @hide */ @@ -761,7 +786,7 @@ public final class SurfaceControl implements Parcelable { return setFlags(FX_SURFACE_EFFECT, FX_SURFACE_MASK); } - private boolean isColorLayerSet() { + private boolean isEffectLayer() { return (mFlags & FX_SURFACE_EFFECT) == FX_SURFACE_EFFECT; } @@ -786,7 +811,7 @@ public final class SurfaceControl implements Parcelable { return setFlags(FX_SURFACE_CONTAINER, FX_SURFACE_MASK); } - private boolean isContainerLayerSet() { + private boolean isContainerLayer() { return (mFlags & FX_SURFACE_CONTAINER) == FX_SURFACE_CONTAINER; } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 9b5b8824b0e6..a5ec4e900641 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -209,7 +209,11 @@ public class WindowlessWindowManager implements IWindowSession { /** @hide */ protected SurfaceControl getSurfaceControl(View rootView) { - final State s = mStateForWindow.get(rootView.getViewRootImpl().mWindow.asBinder()); + final ViewRootImpl root = rootView.getViewRootImpl(); + if (root == null) { + return null; + } + final State s = mStateForWindow.get(root.mWindow.asBinder()); if (s == null) { return null; } diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index 9a732455113c..8be37e9e492d 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -264,6 +264,29 @@ public final class WindowContainerTransaction implements Parcelable { return this; } + /** + * Merges another WCT into this one. + * @param transfer When true, this will transfer everything from other potentially leaving + * other in an unusable state. When false, other is left alone, but + * SurfaceFlinger Transactions will not be merged. + * @hide + */ + public void merge(WindowContainerTransaction other, boolean transfer) { + for (int i = 0, n = other.mChanges.size(); i < n; ++i) { + final IBinder key = other.mChanges.keyAt(i); + Change existing = mChanges.get(key); + if (existing == null) { + existing = new Change(); + mChanges.put(key, existing); + } + existing.merge(other.mChanges.valueAt(i), transfer); + } + for (int i = 0, n = other.mHierarchyOps.size(); i < n; ++i) { + mHierarchyOps.add(transfer ? other.mHierarchyOps.get(i) + : new HierarchyOp(other.mHierarchyOps.get(i))); + } + } + /** @hide */ public Map<IBinder, Change> getChanges() { return mChanges; @@ -359,6 +382,41 @@ public final class WindowContainerTransaction implements Parcelable { mActivityWindowingMode = in.readInt(); } + /** + * @param transfer When true, this will transfer other into this leaving other in an + * undefined state. Use this if you don't intend to use other. When false, + * SurfaceFlinger Transactions will not merge. + */ + public void merge(Change other, boolean transfer) { + mConfiguration.setTo(other.mConfiguration, other.mConfigSetMask, other.mWindowSetMask); + mConfigSetMask |= other.mConfigSetMask; + mWindowSetMask |= other.mWindowSetMask; + if ((other.mChangeMask & CHANGE_FOCUSABLE) != 0) { + mFocusable = other.mFocusable; + } + if (transfer && (other.mChangeMask & CHANGE_BOUNDS_TRANSACTION) != 0) { + mBoundsChangeTransaction = other.mBoundsChangeTransaction; + other.mBoundsChangeTransaction = null; + } + if ((other.mChangeMask & CHANGE_PIP_CALLBACK) != 0) { + mPinnedBounds = transfer ? other.mPinnedBounds : new Rect(other.mPinnedBounds); + } + if ((other.mChangeMask & CHANGE_HIDDEN) != 0) { + mHidden = other.mHidden; + } + mChangeMask |= other.mChangeMask; + if (other.mActivityWindowingMode >= 0) { + mActivityWindowingMode = other.mActivityWindowingMode; + } + if (other.mWindowingMode >= 0) { + mWindowingMode = other.mWindowingMode; + } + if (other.mBoundsChangeSurfaceBounds != null) { + mBoundsChangeSurfaceBounds = transfer ? other.mBoundsChangeSurfaceBounds + : new Rect(other.mBoundsChangeSurfaceBounds); + } + } + public int getWindowingMode() { return mWindowingMode; } @@ -522,6 +580,12 @@ public final class WindowContainerTransaction implements Parcelable { mToTop = toTop; } + public HierarchyOp(@NonNull HierarchyOp copy) { + mContainer = copy.mContainer; + mReparent = copy.mReparent; + mToTop = copy.mToTop; + } + protected HierarchyOp(Parcel in) { mContainer = in.readStrongBinder(); mReparent = in.readStrongBinder(); diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 5533e1eda52d..2a43287a3ae3 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -2182,6 +2182,9 @@ public class ChooserActivity extends ResolverActivity implements } void updateModelAndChooserCounts(TargetInfo info) { + if (info != null && info instanceof MultiDisplayResolveInfo) { + info = ((MultiDisplayResolveInfo) info).getSelectedTarget(); + } if (info != null) { sendClickToAppPredictor(info); final ResolveInfo ri = info.getResolveInfo(); @@ -2784,6 +2787,13 @@ public class ChooserActivity extends ResolverActivity implements return; } + // no need to query direct share for work profile when its turned off + UserManager userManager = getSystemService(UserManager.class); + if (userManager.isQuietModeEnabled(chooserListAdapter.getUserHandle())) { + getChooserActivityLogger().logSharesheetAppLoadComplete(); + return; + } + if (ChooserFlags.USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS || ChooserFlags.USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (DEBUG) { @@ -3016,6 +3026,10 @@ public class ChooserActivity extends ResolverActivity implements currentRootAdapter.updateDirectShareExpansion(); } + void prepareIntentForCrossProfileLaunch(Intent intent) { + intent.fixUris(UserHandle.myUserId()); + } + /** * Adapter for all types of items and targets in ShareSheet. * Note that ranked sections like Direct Share - while appearing grid-like - are handled on the diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index a87f8477bcf4..f4fb993fbb93 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -80,6 +80,7 @@ public class ChooserListAdapter extends ResolverListAdapter { private static final int MAX_SUGGESTED_APP_TARGETS = 4; private static final int MAX_CHOOSER_TARGETS_PER_APP = 2; private static final int MAX_SERVICE_TARGET_APP = 8; + private static final int DEFAULT_DIRECT_SHARE_RANKING_SCORE = 1000; static final int MAX_SERVICE_TARGETS = 8; @@ -564,11 +565,13 @@ public class ChooserListAdapter extends ResolverListAdapter { } Map<String, Integer> scores = mChooserTargetScores.get(componentName); Collections.sort(mParkingDirectShareTargets.get(componentName).first, (o1, o2) -> { - // The score has been normalized between 0 and 2, the default is 1. + // The score has been normalized between 0 and 2000, the default is 1000. int score1 = scores.getOrDefault( - ChooserUtil.md5(o1.getChooserTarget().getTitle().toString()), 1); + ChooserUtil.md5(o1.getChooserTarget().getTitle().toString()), + DEFAULT_DIRECT_SHARE_RANKING_SCORE); int score2 = scores.getOrDefault( - ChooserUtil.md5(o2.getChooserTarget().getTitle().toString()), 1); + ChooserUtil.md5(o2.getChooserTarget().getTitle().toString()), + DEFAULT_DIRECT_SHARE_RANKING_SCORE); return score2 - score1; }); } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index b82f0dfcbe12..f96f560fc60f 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -1235,8 +1235,8 @@ public class ResolverActivity extends Activity implements } if (target != null) { - if (intent != null) { - intent.fixUris(UserHandle.myUserId()); + if (intent != null && isLaunchingTargetInOtherProfile()) { + prepareIntentForCrossProfileLaunch(intent); } safelyStartActivity(target); @@ -1250,6 +1250,13 @@ public class ResolverActivity extends Activity implements return true; } + void prepareIntentForCrossProfileLaunch(Intent intent) {} + + private boolean isLaunchingTargetInOtherProfile() { + return mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier() + != UserHandle.myUserId(); + } + @VisibleForTesting public void safelyStartActivity(TargetInfo cti) { // We're dispatching intents that might be coming from legacy apps, so diff --git a/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java b/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java index e58258352106..cf921d734d48 100644 --- a/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java +++ b/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java @@ -70,6 +70,13 @@ public class MultiDisplayResolveInfo extends DisplayResolveInfo { } /** + * Return selected target. + */ + public DisplayResolveInfo getSelectedTarget() { + return hasSelected() ? mTargetInfos.get(mSelected) : null; + } + + /** * Whether or not the user has selected a specific target for this MultiInfo. */ public boolean hasSelected() { diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index 72162c44ec29..981bf7af9f25 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -233,7 +233,6 @@ public abstract class MediaRoute2ProviderService extends Service { String sessionId = sessionInfo.getId(); synchronized (mSessionLock) { if (mSessionInfo.containsKey(sessionId)) { - // TODO: Notify failure to the requester, and throw exception if needed. Log.w(TAG, "Ignoring duplicate session id."); return; } @@ -244,7 +243,7 @@ public abstract class MediaRoute2ProviderService extends Service { return; } try { - // TODO: Calling binder calls in multiple thread may cause timing issue. + // TODO(b/157873487): Calling binder calls in multiple thread may cause timing issue. // Consider to change implementations to avoid the problems. // For example, post binder calls, always send all sessions at once, etc. mRemoteCallback.notifySessionCreated(requestId, sessionInfo); @@ -519,7 +518,7 @@ public abstract class MediaRoute2ProviderService extends Service { requestCreateSession)); } - //TODO: Ignore requests with unknown session ID. + //TODO(b/157873546): Ignore requests with unknown session ID. -> For all similar commands. @Override public void selectRoute(long requestId, String sessionId, String routeId) { if (!checkCallerisSystem()) { diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 6179b483ca53..6634d4b4190e 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -54,7 +54,7 @@ import java.util.stream.Collectors; * Media Router 2 allows applications to control the routing of media channels * and streams from the current device to remote speakers and devices. */ -// TODO: Add method names at the beginning of log messages. (e.g. updateControllerOnHandler) +// TODO(b/157873330): Add method names at the beginning of log messages. (e.g. selectRoute) // Not only MediaRouter2, but also to service / manager / provider. // TODO: ensure thread-safe and document it public final class MediaRouter2 { @@ -399,7 +399,7 @@ public final class MediaRouter2 { Objects.requireNonNull(controller, "controller must not be null"); Objects.requireNonNull(route, "route must not be null"); - // TODO: Check thread-safety + // TODO(b/157873496): Check thread-safety, at least check "sRouterLock" for every variable if (!mRoutes.containsKey(route.getId())) { notifyTransferFailure(route); return; @@ -501,7 +501,7 @@ public final class MediaRouter2 { } void addRoutesOnHandler(List<MediaRoute2Info> routes) { - // TODO: When onRoutesAdded is first called, + // TODO(b/157874065): When onRoutesAdded is first called, // 1) clear mRoutes before adding the routes // 2) Call onRouteSelected(system_route, reason_fallback) if previously selected route // does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'. @@ -1214,7 +1214,7 @@ public final class MediaRouter2 { * Any operations on this controller after calling this method will be ignored. * The devices that are playing media will stop playing it. */ - // TODO: Add tests using {@link MediaRouter2Manager#getActiveSessions()}. + // TODO(b/157872573): Add tests using {@link MediaRouter2Manager#getActiveSessions()}. public void release() { releaseInternal(/* shouldReleaseSession= */ true, /* shouldNotifyStop= */ true); } diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 4ebfce830a70..a382c2de223e 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -151,8 +151,6 @@ public final class MediaRouter2Manager { return null; } - //TODO: Use cache not to create array. For now, it's unclear when to purge the cache. - //Do this when we finalize how to set control categories. /** * Gets available routes for an application. * @@ -339,7 +337,7 @@ public final class MediaRouter2Manager { Objects.requireNonNull(sessionInfo, "sessionInfo must not be null"); Objects.requireNonNull(route, "route must not be null"); - //TODO: Ignore unknown route. + //TODO(b/157875504): Ignore unknown route. if (sessionInfo.getTransferableRoutes().contains(route.getId())) { transferToRoute(sessionInfo, route); return; @@ -355,7 +353,7 @@ public final class MediaRouter2Manager { if (client != null) { try { int requestId = mNextRequestId.getAndIncrement(); - //TODO: Ensure that every request is eventually removed. + //TODO(b/157875723): Ensure that every request is eventually removed. (Memory leak) mTransferRequests.add(new TransferRequest(requestId, sessionInfo, route)); mMediaRouterService.requestCreateSessionWithManager( diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java index 1f7b5ad51d9c..fbf38dc4d808 100644 --- a/media/java/android/media/ThumbnailUtils.java +++ b/media/java/android/media/ThumbnailUtils.java @@ -34,6 +34,7 @@ import android.graphics.ImageDecoder.ImageInfo; import android.graphics.ImageDecoder.Source; import android.graphics.Matrix; import android.graphics.Rect; +import android.media.MediaMetadataRetriever.BitmapParams; import android.net.Uri; import android.os.Build; import android.os.CancellationSignal; @@ -365,6 +366,9 @@ public class ThumbnailUtils { return ImageDecoder.decodeBitmap(ImageDecoder.createSource(raw), resizer); } + final BitmapParams params = new BitmapParams(); + params.setPreferredConfig(Bitmap.Config.ARGB_8888); + final int width = Integer.parseInt(mmr.extractMetadata(METADATA_KEY_VIDEO_WIDTH)); final int height = Integer.parseInt(mmr.extractMetadata(METADATA_KEY_VIDEO_HEIGHT)); // Fall back to middle of video @@ -376,11 +380,11 @@ public class ThumbnailUtils { // return a frame without up-scaling it if (size.getWidth() > width && size.getHeight() > height) { return Objects.requireNonNull( - mmr.getFrameAtTime(thumbnailTimeUs, OPTION_CLOSEST_SYNC)); + mmr.getFrameAtTime(thumbnailTimeUs, OPTION_CLOSEST_SYNC, params)); } else { return Objects.requireNonNull( mmr.getScaledFrameAtTime(thumbnailTimeUs, OPTION_CLOSEST_SYNC, - size.getWidth(), size.getHeight())); + size.getWidth(), size.getHeight(), params)); } } catch (RuntimeException e) { throw new IOException("Failed to create thumbnail", e); diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp index c3abdc22b19d..f8b4bdb1f4d5 100644 --- a/media/jni/soundpool/Sound.cpp +++ b/media/jni/soundpool/Sound.cpp @@ -31,7 +31,7 @@ constexpr size_t kDefaultHeapSize = 1024 * 1024; // 1MB (compatible with low m Sound::Sound(int32_t soundID, int fd, int64_t offset, int64_t length) : mSoundID(soundID) - , mFd(fcntl(fd, F_DUPFD_CLOEXEC)) // like dup(fd) but closes on exec to prevent leaks. + , mFd(fcntl(fd, F_DUPFD_CLOEXEC, (int)0 /* arg */)) // dup(fd) + close on exec to prevent leaks. , mOffset(offset) , mLength(length) { diff --git a/media/jni/soundpool/SoundDecoder.cpp b/media/jni/soundpool/SoundDecoder.cpp index 6614fdb5af53..5ed10b0d785f 100644 --- a/media/jni/soundpool/SoundDecoder.cpp +++ b/media/jni/soundpool/SoundDecoder.cpp @@ -107,7 +107,8 @@ void SoundDecoder::loadSound(int32_t soundID) } // Launch threads as needed. The "as needed" is weakly consistent as we release mLock. if (pendingSounds > mThreadPool->getActiveThreadCount()) { - const int32_t id __unused = mThreadPool->launch([this](int32_t id) { run(id); }); + const int32_t id = mThreadPool->launch([this](int32_t id) { run(id); }); + (void)id; // avoid clang warning -Wunused-variable -Wused-but-marked-unused ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id); } } diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp index a6d975851619..e7042d0562a4 100644 --- a/media/jni/soundpool/Stream.cpp +++ b/media/jni/soundpool/Stream.cpp @@ -203,7 +203,7 @@ void Stream::stop() void Stream::stop_l() { if (mState != IDLE) { - ALOGV("%s: track streamID: %d", __func__, (int)mStreamID); + ALOGV("%s: track(%p) streamID: %d", __func__, mAudioTrack.get(), (int)mStreamID); if (mAudioTrack != nullptr) { mAudioTrack->stop(); } @@ -232,7 +232,7 @@ Stream* Stream::playPairStream() { LOG_ALWAYS_FATAL_IF(pairStream == nullptr, "No pair stream!"); sp<AudioTrack> releaseTracks[2]; { - ALOGV("%s: track streamID: %d", __func__, (int)mStreamID); + ALOGV("%s: track streamID: %d", __func__, (int)getStreamID()); // TODO: Do we really want to force a simultaneous synchronization between // the stream and its pair? @@ -390,10 +390,10 @@ void Stream::staticCallback(int event, void* user, void* info) void Stream::callback(int event, void* info, int toggle, int tries) { - ALOGV("%s streamID %d", __func__, (int)mStreamID); int32_t activeStreamIDToRestart = 0; { std::unique_lock lock(mLock); + ALOGV("%s track(%p) streamID %d", __func__, mAudioTrack.get(), (int)mStreamID); if (mAudioTrack == nullptr) { // The AudioTrack is either with this stream or its pair. @@ -403,6 +403,7 @@ void Stream::callback(int event, void* info, int toggle, int tries) // logic here. if (tries < 3) { lock.unlock(); + ALOGV("%s streamID %d going to pair stream", __func__, (int)mStreamID); getPairStream()->callback(event, info, toggle, tries + 1); } else { ALOGW("%s streamID %d cannot find track", __func__, (int)mStreamID); @@ -449,8 +450,9 @@ void Stream::callback(int event, void* info, int toggle, int tries) void Stream::dump() const { + // TODO: consider std::try_lock() - ok for now for ALOGV. ALOGV("mPairStream=%p, mState=%d, mStreamID=%d, mSoundID=%d, mPriority=%d, mLoop=%d", - getPairStream(), mState, (int)mStreamID, mSoundID, mPriority, mLoop); + getPairStream(), mState, (int)getStreamID(), getSoundID(), mPriority, mLoop); } } // namespace android::soundpool diff --git a/media/jni/soundpool/Stream.h b/media/jni/soundpool/Stream.h index fd929210eb46..d4e5c9fe7f8a 100644 --- a/media/jni/soundpool/Stream.h +++ b/media/jni/soundpool/Stream.h @@ -88,7 +88,7 @@ public: void resume(int32_t streamID); void autoResume(); void mute(bool muting); - void dump() const; + void dump() const NO_THREAD_SAFETY_ANALYSIS; // disable for ALOGV (see func for details). // returns the pair stream if successful, nullptr otherwise Stream* playPairStream(); diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp index 9ff4254284dc..5b6494d4947e 100644 --- a/media/jni/soundpool/StreamManager.cpp +++ b/media/jni/soundpool/StreamManager.cpp @@ -249,7 +249,8 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound, } // lock if (launchThread) { - const int32_t id __unused = mThreadPool->launch([this](int32_t id) { run(id); }); + const int32_t id = mThreadPool->launch([this](int32_t id) { run(id); }); + (void)id; // avoid clang warning -Wunused-variable -Wused-but-marked-unused ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id); } ALOGV("%s: returning %d", __func__, streamID); @@ -277,7 +278,8 @@ void StreamManager::moveToRestartQueue( sanityCheckQueue_l(); } if (restart) { - const int32_t id __unused = mThreadPool->launch([this](int32_t id) { run(id); }); + const int32_t id = mThreadPool->launch([this](int32_t id) { run(id); }); + (void)id; // avoid clang warning -Wunused-variable -Wused-but-marked-unused ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id); } } diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java index c05c21cf2752..1e49f49b37bc 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java @@ -109,7 +109,7 @@ public class MediaRouter2ManagerTest { mContext = InstrumentationRegistry.getTargetContext(); mManager = MediaRouter2Manager.getInstance(mContext); mRouter2 = MediaRouter2.getInstance(mContext); - //TODO: If we need to support thread pool executors, change this to thread pool executor. + // If we need to support thread pool executors, change this to thread pool executor. mExecutor = Executors.newSingleThreadExecutor(); mPackageName = mContext.getPackageName(); } @@ -253,7 +253,6 @@ public class MediaRouter2ManagerTest { CountDownLatch latch = new CountDownLatch(1); addManagerCallback(new MediaRouter2Manager.Callback()); - //TODO: remove this when it's not necessary. addRouterCallback(new MediaRouter2.RouteCallback() {}); addTransferCallback(new MediaRouter2.TransferCallback() { @Override diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml index 3a0bc2d2eb77..7f10edf158b6 100644 --- a/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml +++ b/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml @@ -18,5 +18,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="enabled_by_admin" msgid="6630472777476410137">"Aktiveret af administratoren"</string> - <string name="disabled_by_admin" msgid="4023569940620832713">"Deaktiveret af administratoren"</string> + <string name="disabled_by_admin" msgid="4023569940620832713">"Deaktiveret af administrator"</string> </resources> diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml index aaf607f6f3ce..2a881247c3af 100644 --- a/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml +++ b/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml @@ -18,5 +18,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="enabled_by_admin" msgid="6630472777476410137">"Administratzaileak gaitu egin du"</string> - <string name="disabled_by_admin" msgid="4023569940620832713">"Administratzaileak desgaitu egin du"</string> + <string name="disabled_by_admin" msgid="4023569940620832713">"Administratzaileak desgaitu du"</string> </resources> diff --git a/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml b/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml index 9d83396689bd..34cb8e0fda38 100644 --- a/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"Pretraži postavke"</string> + <string name="search_menu" msgid="1914043873178389845">"Pretražite postavke"</string> </resources> diff --git a/packages/SettingsLib/SearchWidget/res/values-is/strings.xml b/packages/SettingsLib/SearchWidget/res/values-is/strings.xml index 7ab103b476f3..3378c84d7e08 100644 --- a/packages/SettingsLib/SearchWidget/res/values-is/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-is/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"Leitarstillingar"</string> + <string name="search_menu" msgid="1914043873178389845">"Leita í stillingum"</string> </resources> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 380cd8ec1fba..b501c656a680 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -196,7 +196,7 @@ <string name="choose_profile" msgid="343803890897657450">"Chọn hồ sơ"</string> <string name="category_personal" msgid="6236798763159385225">"Cá nhân"</string> <string name="category_work" msgid="4014193632325996115">"Cơ quan"</string> - <string name="development_settings_title" msgid="140296922921597393">"Tùy chọn nhà phát triển"</string> + <string name="development_settings_title" msgid="140296922921597393">"Tùy chọn cho nhà phát triển"</string> <string name="development_settings_enable" msgid="4285094651288242183">"Bật tùy chọn nhà phát triển"</string> <string name="development_settings_summary" msgid="8718917813868735095">"Đặt tùy chọn cho phát triển ứng dụng"</string> <string name="development_settings_not_available" msgid="355070198089140951">"Tùy chọn dành cho nhà phát triển không khả dụng cho người dùng này"</string> diff --git a/packages/SettingsProvider/res/values-fa/strings.xml b/packages/SettingsProvider/res/values-fa/strings.xml index cc0b55728310..946e2c07c576 100644 --- a/packages/SettingsProvider/res/values-fa/strings.xml +++ b/packages/SettingsProvider/res/values-fa/strings.xml @@ -19,7 +19,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4567566098528588863">"تنظیم محل ذخیره"</string> + <string name="app_label" msgid="4567566098528588863">"تنظیم محل فضای ذخیرهسازی"</string> <string name="wifi_softap_config_change" msgid="5688373762357941645">"تنظیمات نقطه اتصال تغییر کرده است"</string> <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"برای مشاهده جزئیات ضربه بزنید"</string> </resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index 028c3041a50d..75b680dd3a88 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -80,6 +80,7 @@ public class SettingsHelper { sBroadcastOnRestore.add(Settings.Secure.UI_NIGHT_MODE); sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_START_TIME); sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_END_TIME); + sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); } private interface SettingsLookup { diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java index 54f8688bf5d6..197788e11973 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java @@ -31,6 +31,7 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; /** * Tests for {@link SettingsHelper#restoreValue(Context, ContentResolver, ContentValues, Uri, @@ -89,7 +90,7 @@ public class SettingsHelperRestoreTest { float restoreSettingValue = defaultSettingValue + 0.5f; mSettingsHelper.restoreValue( - mContext, + Mockito.mock(Context.class), mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), @@ -132,7 +133,7 @@ public class SettingsHelperRestoreTest { Settings.Secure.putInt(mContentResolver, settingName, configuredSettingValue); mSettingsHelper.restoreValue( - mContext, + Mockito.mock(Context.class), mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), @@ -154,7 +155,7 @@ public class SettingsHelperRestoreTest { int restoreSettingValue = 1; mSettingsHelper.restoreValue( - mContext, + Mockito.mock(Context.class), mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), diff --git a/packages/SystemUI/res/drawable/ic_device_air_freshener.xml b/packages/SystemUI/res/drawable/ic_device_air_freshener.xml new file mode 100644 index 000000000000..5050223302b3 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_air_freshener.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_air_freshener_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_air_freshener_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_air_purifier.xml b/packages/SystemUI/res/drawable/ic_device_air_purifier.xml new file mode 100644 index 000000000000..7de46bf24be4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_air_purifier.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_air_purifier_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_air_purifier_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_blinds.xml b/packages/SystemUI/res/drawable/ic_device_blinds.xml new file mode 100644 index 000000000000..104da7e66887 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_blinds.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_blinds_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_blinds_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_blinds_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_blinds_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_blinds_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_blinds_off_anim.xml new file mode 100644 index 000000000000..1eaccf58ac9f --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_blinds_off_anim.xml @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G_N_2_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_2_G_T_1" android:translateX="0" android:translateY="-3.032"> + <group android:name="_R_G_L_2_G" android:translateY="3.032"> + <group android:name="_R_G_L_2_C_0_G"> + <clip-path android:name="_R_G_L_2_C_0" android:pathData=" M10.68 -9.87 C10.68,-9.87 -10.19,-9.87 -10.19,-9.87 C-10.19,-9.87 -10.19,7.92 -10.19,7.92 C-10.19,7.92 10.68,7.92 10.68,7.92 C10.68,7.92 10.68,-9.87 10.68,-9.87c "/> + <group android:name="_R_G_L_2_C_0_G_G"> + <path android:name="_R_G_L_2_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 -1 C-6,-1 -6,-6.47 -6,-6.47 C-6,-6.47 6,-6.47 6,-6.47 C6,-6.47 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,1.28 1,1.28 C1.38,1.5 1.68,1.84 1.85,2.24 C2.02,2.65 2.05,3.1 1.93,3.53 C1.82,3.95 1.57,4.33 1.22,4.6 C0.87,4.86 0.44,5.01 0,5.01 C-0.44,5.01 -0.87,4.86 -1.22,4.6 C-1.57,4.33 -1.82,3.95 -1.93,3.53 C-2.05,3.1 -2.02,2.65 -1.85,2.24 C-1.68,1.84 -1.38,1.5 -1,1.28 C-1,1.28 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_1_G_N_2_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 -5.97 C-6,-5.97 -6,6 -6,6 C-6,6 6,6 6,6 C6,6 6,-5.97 6,-5.97 C6,-5.97 -6,-5.97 -6,-5.97c M8 -8 C8,-8 8,6 8,6 C8,6 10,6 10,6 C10,6 10,8 10,8 C10,8 -10,8 -10,8 C-10,8 -10,6 -10,6 C-10,6 -8,6 -8,6 C-8,6 -8,-8 -8,-8 C-8,-8 8,-8 8,-8c "/> + </group> + </group> + <group android:name="_R_G_L_0_G_N_2_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_0_G_T_1" android:translateX="0" android:translateY="-13.407"> + <group android:name="_R_G_L_0_G" android:translateY="3.032"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M10.68 2.46 C10.68,2.46 -10.19,2.46 -10.19,2.46 C-10.19,2.46 -10.19,20.26 -10.19,20.26 C-10.19,20.26 10.68,20.26 10.68,20.26 C10.68,20.26 10.68,2.46 10.68,2.46c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 -1 C-6,-1 -6,-3.03 -6,-3.03 C-6,-3.03 6,-3.03 6,-3.03 C6,-3.03 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,-0.47 1,-0.47 C1.38,-0.25 1.68,0.09 1.85,0.49 C2.02,0.9 2.05,1.35 1.93,1.78 C1.82,2.2 1.57,2.58 1.22,2.85 C0.87,3.11 0.44,3.26 0,3.26 C-0.44,3.26 -0.87,3.11 -1.22,2.85 C-1.57,2.58 -1.82,2.2 -1.93,1.78 C-2.05,1.35 -2.02,0.9 -1.85,0.49 C-1.68,0.09 -1.38,-0.25 -1,-0.47 C-1,-0.47 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c "/> + </group> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="317" android:startOffset="0" android:valueFrom="M10.68 -9.87 C10.68,-9.87 -10.19,-9.87 -10.19,-9.87 C-10.19,-9.87 -10.19,7.92 -10.19,7.92 C-10.19,7.92 10.68,7.92 10.68,7.92 C10.68,7.92 10.68,-9.87 10.68,-9.87c " android:valueTo="M10.68 -19.87 C10.68,-19.87 -10.19,-19.87 -10.19,-19.87 C-10.19,-19.87 -10.19,-6.87 -10.19,-6.87 C-10.19,-6.87 10.68,-6.87 10.68,-6.87 C10.68,-6.87 10.68,-19.87 10.68,-19.87c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="317" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-3.032C 0,-3.516 0,10.093 0,10.093"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M10.68 2.46 C10.68,2.46 -10.19,2.46 -10.19,2.46 C-10.19,2.46 -10.19,20.26 -10.19,20.26 C-10.19,20.26 10.68,20.26 10.68,20.26 C10.68,20.26 10.68,2.46 10.68,2.46c " android:valueTo="M10.68 2.46 C10.68,2.46 -10.19,2.46 -10.19,2.46 C-10.19,2.46 -10.19,20.26 -10.19,20.26 C-10.19,20.26 10.68,20.26 10.68,20.26 C10.68,20.26 10.68,2.46 10.68,2.46c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="433" android:startOffset="67" android:valueFrom="M10.68 2.46 C10.68,2.46 -10.19,2.46 -10.19,2.46 C-10.19,2.46 -10.19,20.26 -10.19,20.26 C-10.19,20.26 10.68,20.26 10.68,20.26 C10.68,20.26 10.68,2.46 10.68,2.46c " android:valueTo="M10.68 -7.87 C10.68,-7.87 -10.19,-7.87 -10.19,-7.87 C-10.19,-7.87 -10.19,9.92 -10.19,9.92 C-10.19,9.92 10.68,9.92 10.68,9.92 C10.68,9.92 10.68,-7.87 10.68,-7.87c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-6 -1 C-6,-1 -6,-3.03 -6,-3.03 C-6,-3.03 6,-3.03 6,-3.03 C6,-3.03 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,-0.47 1,-0.47 C1.38,-0.25 1.68,0.09 1.85,0.49 C2.02,0.9 2.05,1.35 1.93,1.78 C1.82,2.2 1.57,2.58 1.22,2.85 C0.87,3.11 0.44,3.26 0,3.26 C-0.44,3.26 -0.87,3.11 -1.22,2.85 C-1.57,2.58 -1.82,2.2 -1.93,1.78 C-2.05,1.35 -2.02,0.9 -1.85,0.49 C-1.68,0.09 -1.38,-0.25 -1,-0.47 C-1,-0.47 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c " android:valueTo="M-6 -1 C-6,-1 -6,-3.03 -6,-3.03 C-6,-3.03 6,-3.03 6,-3.03 C6,-3.03 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,-0.47 1,-0.47 C1.38,-0.25 1.68,0.09 1.85,0.49 C2.02,0.9 2.05,1.35 1.93,1.78 C1.82,2.2 1.57,2.58 1.22,2.85 C0.87,3.11 0.44,3.26 0,3.26 C-0.44,3.26 -0.87,3.11 -1.22,2.85 C-1.57,2.58 -1.82,2.2 -1.93,1.78 C-2.05,1.35 -2.02,0.9 -1.85,0.49 C-1.68,0.09 -1.38,-0.25 -1,-0.47 C-1,-0.47 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="433" android:startOffset="67" android:valueFrom="M-6 -1 C-6,-1 -6,-3.03 -6,-3.03 C-6,-3.03 6,-3.03 6,-3.03 C6,-3.03 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,-0.47 1,-0.47 C1.38,-0.25 1.68,0.09 1.85,0.49 C2.02,0.9 2.05,1.35 1.93,1.78 C1.82,2.2 1.57,2.58 1.22,2.85 C0.87,3.11 0.44,3.26 0,3.26 C-0.44,3.26 -0.87,3.11 -1.22,2.85 C-1.57,2.58 -1.82,2.2 -1.93,1.78 C-2.05,1.35 -2.02,0.9 -1.85,0.49 C-1.68,0.09 -1.38,-0.25 -1,-0.47 C-1,-0.47 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c " android:valueTo="M-6 -1 C-6,-1 -6,-3.03 -6,-3.03 C-6,-3.03 6,-3.03 6,-3.03 C6,-3.03 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,1.28 1,1.28 C1.38,1.5 1.68,1.84 1.85,2.24 C2.02,2.65 2.05,3.1 1.93,3.53 C1.82,3.95 1.57,4.33 1.22,4.6 C0.87,4.86 0.44,5.01 0,5.01 C-0.44,5.01 -0.87,4.86 -1.22,4.6 C-1.57,4.33 -1.82,3.95 -1.93,3.53 C-2.05,3.1 -2.02,2.65 -1.85,2.24 C-1.68,1.84 -1.38,1.5 -1,1.28 C-1,1.28 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-13.407C 0,-13.407 0,-12.568 0,-13.407"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="433" android:startOffset="67" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-13.407C 0,-13.407 0,-2.193 0,-3.032"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_2_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_blinds_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_blinds_on_anim.xml new file mode 100644 index 000000000000..de87f8112a9b --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_blinds_on_anim.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_2_G_T_1" android:translateX="0" android:translateY="-3.032"> + <group android:name="_R_G_L_2_G" android:translateY="3.032"> + <group android:name="_R_G_L_2_C_0_G"> + <clip-path android:name="_R_G_L_2_C_0" android:pathData=" M10.68 -9.87 C10.68,-9.87 -10.19,-9.87 -10.19,-9.87 C-10.19,-9.87 -10.19,7.92 -10.19,7.92 C-10.19,7.92 10.68,7.92 10.68,7.92 C10.68,7.92 10.68,-9.87 10.68,-9.87c "/> + <group android:name="_R_G_L_2_C_0_G_G"> + <path android:name="_R_G_L_2_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 -1 C-6,-1 -6,-3.03 -6,-3.03 C-6,-3.03 6,-3.03 6,-3.03 C6,-3.03 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,1.28 1,1.28 C1.38,1.5 1.68,1.84 1.85,2.24 C2.02,2.65 2.05,3.1 1.93,3.53 C1.82,3.95 1.57,4.33 1.22,4.6 C0.87,4.86 0.44,5.01 0,5.01 C-0.44,5.01 -0.87,4.86 -1.22,4.6 C-1.57,4.33 -1.82,3.95 -1.93,3.53 C-2.05,3.1 -2.02,2.65 -1.85,2.24 C-1.68,1.84 -1.38,1.5 -1,1.28 C-1,1.28 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 -5.97 C-6,-5.97 -6,6 -6,6 C-6,6 6,6 6,6 C6,6 6,-5.97 6,-5.97 C6,-5.97 -6,-5.97 -6,-5.97c M8 -8 C8,-8 8,6 8,6 C8,6 10,6 10,6 C10,6 10,8 10,8 C10,8 -10,8 -10,8 C-10,8 -10,6 -10,6 C-10,6 -8,6 -8,6 C-8,6 -8,-8 -8,-8 C-8,-8 8,-8 8,-8c "/> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_0_G_T_1" android:translateX="0" android:translateY="-8.064"> + <group android:name="_R_G_L_0_G" android:translateY="3.032"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M7.78 -2 C7.78,-2 -7.75,-2 -7.75,-2 C-7.75,-2 -7.75,12.15 -7.75,12.15 C-7.75,12.15 7.78,12.15 7.78,12.15 C7.78,12.15 7.78,-2 7.78,-2c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 -5.37 C-6,-5.37 -6,-6.88 -6,-6.88 C-6,-6.88 6,-6.88 6,-6.88 C6,-6.88 6,-5.37 6,-5.37 C6,-5.37 1,-5.37 1,-5.37 C1,-5.37 1,-5.34 1,-5.34 C1.38,-5.12 1.68,-4.78 1.85,-4.37 C2.02,-3.97 2.05,-3.52 1.93,-3.09 C1.82,-2.67 1.57,-2.29 1.22,-2.02 C0.87,-1.75 0.44,-1.61 0,-1.61 C-0.44,-1.61 -0.87,-1.75 -1.22,-2.02 C-1.57,-2.29 -1.82,-2.67 -1.93,-3.09 C-2.05,-3.52 -2.02,-3.97 -1.85,-4.37 C-1.68,-4.78 -1.38,-5.12 -1,-5.34 C-1,-5.34 -1,-5.37 -1,-5.37 C-1,-5.37 -6,-5.37 -6,-5.37c "/> + </group> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="317" android:startOffset="0" android:valueFrom="M10.68 -9.87 C10.68,-9.87 -10.19,-9.87 -10.19,-9.87 C-10.19,-9.87 -10.19,7.92 -10.19,7.92 C-10.19,7.92 10.68,7.92 10.68,7.92 C10.68,7.92 10.68,-9.87 10.68,-9.87c " android:valueTo="M10.68 -19.87 C10.68,-19.87 -10.19,-19.87 -10.19,-19.87 C-10.19,-19.87 -10.19,-2.08 -10.19,-2.08 C-10.19,-2.08 10.68,-2.08 10.68,-2.08 C10.68,-2.08 10.68,-19.87 10.68,-19.87c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="317" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-3.032C 0,-3.516 0,6.968 0,6.968"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M7.78 -2 C7.78,-2 -7.75,-2 -7.75,-2 C-7.75,-2 -7.75,12.15 -7.75,12.15 C-7.75,12.15 7.78,12.15 7.78,12.15 C7.78,12.15 7.78,-2 7.78,-2c " android:valueTo="M7.78 -2 C7.78,-2 -7.75,-2 -7.75,-2 C-7.75,-2 -7.75,12.15 -7.75,12.15 C-7.75,12.15 7.78,12.15 7.78,12.15 C7.78,12.15 7.78,-2 7.78,-2c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="433" android:startOffset="67" android:valueFrom="M7.78 -2 C7.78,-2 -7.75,-2 -7.75,-2 C-7.75,-2 -7.75,12.15 -7.75,12.15 C-7.75,12.15 7.78,12.15 7.78,12.15 C7.78,12.15 7.78,-2 7.78,-2c " android:valueTo="M7.78 -7 C7.78,-7 -7.75,-7 -7.75,-7 C-7.75,-7 -7.75,7.15 -7.75,7.15 C-7.75,7.15 7.78,7.15 7.78,7.15 C7.78,7.15 7.78,-7 7.78,-7c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-6 -5.37 C-6,-5.37 -6,-6.88 -6,-6.88 C-6,-6.88 6,-6.88 6,-6.88 C6,-6.88 6,-5.37 6,-5.37 C6,-5.37 1,-5.37 1,-5.37 C1,-5.37 1,-5.34 1,-5.34 C1.38,-5.12 1.68,-4.78 1.85,-4.37 C2.02,-3.97 2.05,-3.52 1.93,-3.09 C1.82,-2.67 1.57,-2.29 1.22,-2.02 C0.87,-1.75 0.44,-1.61 0,-1.61 C-0.44,-1.61 -0.87,-1.75 -1.22,-2.02 C-1.57,-2.29 -1.82,-2.67 -1.93,-3.09 C-2.05,-3.52 -2.02,-3.97 -1.85,-4.37 C-1.68,-4.78 -1.38,-5.12 -1,-5.34 C-1,-5.34 -1,-5.37 -1,-5.37 C-1,-5.37 -6,-5.37 -6,-5.37c " android:valueTo="M-6 -5.37 C-6,-5.37 -6,-6.88 -6,-6.88 C-6,-6.88 6,-6.88 6,-6.88 C6,-6.88 6,-5.37 6,-5.37 C6,-5.37 1,-5.37 1,-5.37 C1,-5.37 1,-5.34 1,-5.34 C1.38,-5.12 1.68,-4.78 1.85,-4.37 C2.02,-3.97 2.05,-3.52 1.93,-3.09 C1.82,-2.67 1.57,-2.29 1.22,-2.02 C0.87,-1.75 0.44,-1.61 0,-1.61 C-0.44,-1.61 -0.87,-1.75 -1.22,-2.02 C-1.57,-2.29 -1.82,-2.67 -1.93,-3.09 C-2.05,-3.52 -2.02,-3.97 -1.85,-4.37 C-1.68,-4.78 -1.38,-5.12 -1,-5.34 C-1,-5.34 -1,-5.37 -1,-5.37 C-1,-5.37 -6,-5.37 -6,-5.37c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="433" android:startOffset="67" android:valueFrom="M-6 -5.37 C-6,-5.37 -6,-6.88 -6,-6.88 C-6,-6.88 6,-6.88 6,-6.88 C6,-6.88 6,-5.37 6,-5.37 C6,-5.37 1,-5.37 1,-5.37 C1,-5.37 1,-5.34 1,-5.34 C1.38,-5.12 1.68,-4.78 1.85,-4.37 C2.02,-3.97 2.05,-3.52 1.93,-3.09 C1.82,-2.67 1.57,-2.29 1.22,-2.02 C0.87,-1.75 0.44,-1.61 0,-1.61 C-0.44,-1.61 -0.87,-1.75 -1.22,-2.02 C-1.57,-2.29 -1.82,-2.67 -1.93,-3.09 C-2.05,-3.52 -2.02,-3.97 -1.85,-4.37 C-1.68,-4.78 -1.38,-5.12 -1,-5.34 C-1,-5.34 -1,-5.37 -1,-5.37 C-1,-5.37 -6,-5.37 -6,-5.37c " android:valueTo="M-6 -1 C-6,-1 -6,-6.5 -6,-6.5 C-6,-6.5 6,-6.5 6,-6.5 C6,-6.5 6,-1 6,-1 C6,-1 1,-1 1,-1 C1,-1 1,1.28 1,1.28 C1.38,1.5 1.68,1.84 1.85,2.24 C2.02,2.65 2.05,3.1 1.93,3.53 C1.82,3.95 1.57,4.33 1.22,4.6 C0.87,4.86 0.44,5.01 0,5.01 C-0.44,5.01 -0.87,4.86 -1.22,4.6 C-1.57,4.33 -1.82,3.95 -1.93,3.53 C-2.05,3.1 -2.02,2.65 -1.85,2.24 C-1.68,1.84 -1.38,1.5 -1,1.28 C-1,1.28 -1,-1 -1,-1 C-1,-1 -6,-1 -6,-1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-8.064C 0,-8.064 0,-8.903 0,-8.064"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="433" android:startOffset="67" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-8.064C 0,-8.064 0,-3.871 0,-3.032"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_camera.xml b/packages/SystemUI/res/drawable/ic_device_camera.xml new file mode 100644 index 000000000000..a76142ab2cc1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_camera.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_camera_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_camera_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_camera_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_camera_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_camera_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_camera_off_anim.xml new file mode 100644 index 000000000000..32d1a0eb755a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_camera_off_anim.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M4 6 C4,6 4,-2.31 4,-2.31 C4,-2.31 4,-6 4,-6 C4,-6 -8,-6 -8,-6 C-8,-6 -8,6 -8,6 C-8,6 4,6 4,6c M6 -6 C6,-6 6,-1.52 6,-1.52 C6,-1.52 10,-5.5 10,-5.5 C10,-5.5 10,5.5 10,5.5 C10,5.5 6,1.52 6,1.52 C6,1.52 6,6 6,6 C6,6.53 5.79,7.04 5.41,7.41 C5.04,7.79 4.53,8 4,8 C4,8 -8,8 -8,8 C-8.53,8 -9.04,7.79 -9.41,7.41 C-9.79,7.04 -10,6.53 -10,6 C-10,6 -10,-6 -10,-6 C-10,-6.53 -9.79,-7.04 -9.41,-7.41 C-9.04,-7.79 -8.53,-8 -8,-8 C-8,-8 4,-8 4,-8 C4.53,-8 5.04,-7.79 5.41,-7.41 C5.79,-7.04 6,-6.53 6,-6c "/> + </group> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M-2.25 -12.33 C-8.89,-12.33 -14.27,-6.95 -14.27,-0.31 C-14.27,6.32 -8.89,11.71 -2.25,11.71 C4.39,11.71 9.77,6.32 9.77,-0.31 C9.77,-6.95 4.39,-12.33 -2.25,-12.33c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M6 -6 C6,-6 6,-1.52 6,-1.52 C6,-1.52 10,-5.5 10,-5.5 C10,-5.5 10,5.5 10,5.5 C10,5.5 6,1.52 6,1.52 C6,1.52 6,6 6,6 C6,6.53 5.79,7.04 5.41,7.41 C5.04,7.79 4.53,8 4,8 C4,8 -8,8 -8,8 C-8.53,8 -9.04,7.79 -9.41,7.41 C-9.79,7.04 -10,6.53 -10,6 C-10,6 -10,-6 -10,-6 C-10,-6.53 -9.79,-7.04 -9.41,-7.41 C-9.04,-7.79 -8.53,-8 -8,-8 C-8,-8 4,-8 4,-8 C4.53,-8 5.04,-7.79 5.41,-7.41 C5.79,-7.04 6,-6.53 6,-6c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M-2.25 -12.33 C-8.89,-12.33 -14.27,-6.95 -14.27,-0.31 C-14.27,6.32 -8.89,11.71 -2.25,11.71 C4.39,11.71 9.77,6.32 9.77,-0.31 C9.77,-6.95 4.39,-12.33 -2.25,-12.33c " android:valueTo="M-1.84 0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_camera_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_camera_on_anim.xml new file mode 100644 index 000000000000..1a1a3ffe4855 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_camera_on_anim.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M4 6 C4,6 4,-2.31 4,-2.31 C4,-2.31 4,-6 4,-6 C4,-6 -8,-6 -8,-6 C-8,-6 -8,6 -8,6 C-8,6 4,6 4,6c M6 -6 C6,-6 6,-1.52 6,-1.52 C6,-1.52 10,-5.5 10,-5.5 C10,-5.5 10,5.5 10,5.5 C10,5.5 6,1.52 6,1.52 C6,1.52 6,6 6,6 C6,6.53 5.79,7.04 5.41,7.41 C5.04,7.79 4.53,8 4,8 C4,8 -8,8 -8,8 C-8.53,8 -9.04,7.79 -9.41,7.41 C-9.79,7.04 -10,6.53 -10,6 C-10,6 -10,-6 -10,-6 C-10,-6.53 -9.79,-7.04 -9.41,-7.41 C-9.04,-7.79 -8.53,-8 -8,-8 C-8,-8 4,-8 4,-8 C4.53,-8 5.04,-7.79 5.41,-7.41 C5.79,-7.04 6,-6.53 6,-6c "/> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_G"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M-1.84 0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M6 -6 C6,-6 6,-1.52 6,-1.52 C6,-1.52 10,-5.5 10,-5.5 C10,-5.5 10,5.5 10,5.5 C10,5.5 6,1.52 6,1.52 C6,1.52 6,6 6,6 C6,6.53 5.79,7.04 5.41,7.41 C5.04,7.79 4.53,8 4,8 C4,8 -8,8 -8,8 C-8.53,8 -9.04,7.79 -9.41,7.41 C-9.79,7.04 -10,6.53 -10,6 C-10,6 -10,-6 -10,-6 C-10,-6.53 -9.79,-7.04 -9.41,-7.41 C-9.04,-7.79 -8.53,-8 -8,-8 C-8,-8 4,-8 4,-8 C4.53,-8 5.04,-7.79 5.41,-7.41 C5.79,-7.04 6,-6.53 6,-6c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M-1.84 0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09 C-1.84,0.09 -1.84,0.09 -1.84,0.09c " android:valueTo="M-2.25 -12.33 C-8.89,-12.33 -14.27,-6.95 -14.27,-0.31 C-14.27,6.32 -8.89,11.71 -2.25,11.71 C4.39,11.71 9.77,6.32 9.77,-0.31 C9.77,-6.95 4.39,-12.33 -2.25,-12.33c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_cooking.xml b/packages/SystemUI/res/drawable/ic_device_cooking.xml new file mode 100644 index 000000000000..e3922e2f11ea --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_cooking.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_cooking_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_cooking_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_dishwasher.xml b/packages/SystemUI/res/drawable/ic_device_dishwasher.xml new file mode 100644 index 000000000000..cc7f7f98d07e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_dishwasher.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_dishwasher_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_dishwasher_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_display.xml b/packages/SystemUI/res/drawable/ic_device_display.xml new file mode 100644 index 000000000000..9a2ee2995de8 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_display.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_display_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_display_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_door.xml b/packages/SystemUI/res/drawable/ic_device_door.xml new file mode 100644 index 000000000000..367f97f2d3ee --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_door.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_door_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_door_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_doorbell.xml b/packages/SystemUI/res/drawable/ic_device_doorbell.xml new file mode 100644 index 000000000000..6f96a1b719d3 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_doorbell.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_doorbell_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_doorbell_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_drawer.xml b/packages/SystemUI/res/drawable/ic_device_drawer.xml new file mode 100644 index 000000000000..0f86f90d997a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_drawer.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_drawer_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_drawer_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_fan.xml b/packages/SystemUI/res/drawable/ic_device_fan.xml new file mode 100644 index 000000000000..34dc712ace65 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_fan.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_fan_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_fan_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_fan_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_fan_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_fan_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_fan_off_anim.xml new file mode 100644 index 000000000000..189d85a70f79 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_fan_off_anim.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G_N_2_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G_N_2_T_0" android:rotation="180"> + <group android:name="_R_G_L_1_G" android:rotation="360"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M5.4 0.25 C5.99,0.64 6.5,1.14 6.89,1.73 C6.89,1.73 6.89,1.73 6.89,1.73 C6.96,1.84 7.07,1.93 7.19,1.97 C7.31,2.02 7.45,2.03 7.57,1.99 C7.7,1.95 7.81,1.87 7.89,1.76 C7.97,1.66 8,1.53 8,1.39 C8.07,0.81 7.99,0.22 7.78,-0.33 C7.57,-0.88 7.23,-1.37 6.78,-1.76 C6.54,-1.91 6.27,-1.99 5.99,-2 C5.71,-2.01 5.42,-1.95 5.17,-1.82 C5.17,-1.82 3.29,-1.14 3.29,-1.14 C3.36,-0.94 3.42,-0.73 3.45,-0.52 C4.14,-0.4 4.81,-0.14 5.4,0.25c M0.33 7.78 C0.88,7.57 1.37,7.22 1.76,6.78 C1.76,6.78 1.76,6.78 1.76,6.78 C1.9,6.54 1.99,6.27 2,5.99 C2.01,5.71 1.95,5.42 1.82,5.17 C1.82,5.17 1.14,3.29 1.14,3.29 C0.94,3.36 0.73,3.42 0.52,3.45 C0.4,4.14 0.13,4.81 -0.25,5.4 C-0.64,5.99 -1.14,6.5 -1.73,6.89 C-1.84,6.96 -1.93,7.07 -1.97,7.19 C-2.02,7.31 -2.02,7.45 -1.99,7.57 C-1.95,7.7 -1.87,7.81 -1.76,7.89 C-1.66,7.97 -1.53,8 -1.39,8 C-0.81,8.07 -0.22,7.99 0.33,7.78c M-5.99 2 C-5.7,2.01 -5.42,1.95 -5.17,1.82 C-5.17,1.82 -3.29,1.14 -3.29,1.14 C-3.36,0.94 -3.42,0.73 -3.45,0.52 C-4.14,0.4 -4.81,0.14 -5.4,-0.25 C-5.99,-0.64 -6.5,-1.14 -6.89,-1.73 C-6.96,-1.84 -7.06,-1.93 -7.19,-1.97 C-7.31,-2.02 -7.45,-2.02 -7.57,-1.99 C-7.7,-1.95 -7.81,-1.87 -7.89,-1.76 C-7.96,-1.66 -8,-1.53 -8,-1.39 C-8.07,-0.81 -7.99,-0.22 -7.78,0.33 C-7.57,0.88 -7.23,1.37 -6.78,1.75 C-6.54,1.9 -6.27,1.99 -5.99,2c M-0.33 -7.78 C-0.88,-7.57 -1.37,-7.23 -1.75,-6.78 C-1.9,-6.54 -1.99,-6.27 -2,-5.99 C-2.01,-5.7 -1.95,-5.42 -1.82,-5.17 C-1.82,-5.17 -1.14,-3.29 -1.14,-3.29 C-0.94,-3.36 -0.73,-3.41 -0.52,-3.45 C-0.4,-4.14 -0.13,-4.81 0.25,-5.4 C0.64,-5.99 1.14,-6.5 1.73,-6.89 C1.84,-6.96 1.93,-7.06 1.97,-7.19 C2.02,-7.31 2.03,-7.45 1.99,-7.57 C1.95,-7.7 1.87,-7.81 1.76,-7.89 C1.66,-7.96 1.53,-8 1.39,-8 C0.81,-8.07 0.22,-7.99 -0.33,-7.78c M-0.83 1.25 C-0.59,1.41 -0.3,1.5 0,1.5 C0.4,1.5 0.78,1.34 1.06,1.06 C1.34,0.78 1.5,0.4 1.5,0 C1.5,-0.3 1.41,-0.59 1.25,-0.83 C1.08,-1.08 0.85,-1.27 0.57,-1.39 C0.3,-1.5 0,-1.53 -0.29,-1.47 C-0.58,-1.41 -0.85,-1.27 -1.06,-1.06 C-1.27,-0.85 -1.41,-0.58 -1.47,-0.29 C-1.53,0 -1.5,0.3 -1.39,0.57 C-1.27,0.85 -1.08,1.08 -0.83,1.25c M2.06 -2.82 C2.06,-2.82 4.35,-3.64 4.35,-3.64 C6.99,-4.84 10,-3 10,1.39 C10,1.96 9.83,2.5 9.49,2.95 C9.16,3.41 8.69,3.74 8.15,3.9 C7.62,4.06 7.04,4.05 6.51,3.86 C5.99,3.67 5.54,3.31 5.23,2.84 C4.75,2.13 4.01,1.64 3.16,1.48 C3.07,1.68 2.95,1.87 2.82,2.06 C2.82,2.06 3.64,4.35 3.64,4.35 C4.84,6.99 3.01,10 -1.39,10 C-1.95,10 -2.5,9.83 -2.95,9.49 C-3.41,9.16 -3.74,8.69 -3.9,8.15 C-4.06,7.62 -4.05,7.04 -3.86,6.51 C-3.67,5.99 -3.31,5.54 -2.84,5.23 C-2.13,4.75 -1.64,4.01 -1.47,3.16 C-1.68,3.07 -1.87,2.95 -2.06,2.82 C-2.06,2.82 -4.34,3.64 -4.34,3.64 C-6.99,4.84 -10,3.01 -10,-1.39 C-10,-1.95 -9.83,-2.5 -9.49,-2.95 C-9.16,-3.41 -8.69,-3.74 -8.15,-3.9 C-7.62,-4.06 -7.04,-4.05 -6.51,-3.86 C-5.99,-3.66 -5.53,-3.31 -5.23,-2.84 C-4.75,-2.13 -4,-1.64 -3.16,-1.47 C-3.07,-1.68 -2.95,-1.87 -2.82,-2.06 C-2.82,-2.06 -3.64,-4.34 -3.64,-4.34 C-4.84,-6.99 -3.01,-10 1.39,-10 C1.96,-10 2.5,-9.83 2.95,-9.49 C3.41,-9.16 3.74,-8.69 3.9,-8.15 C4.06,-7.62 4.05,-7.04 3.86,-6.51 C3.67,-5.99 3.31,-5.53 2.84,-5.23 C2.13,-4.75 1.64,-4 1.47,-3.16 C1.68,-3.07 1.87,-2.95 2.06,-2.82c "/> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_G" android:rotation="180"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M0.25 -12 C-6.37,-12.14 -11.86,-6.88 -12,-0.25 C-12.14,6.37 -6.88,11.86 -0.25,12 C6.37,12.14 11.86,6.88 12,0.25 C12.14,-6.37 6.88,-11.86 0.25,-12c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.83 1.25 C-0.59,1.41 -0.3,1.5 0,1.5 C0.4,1.5 0.78,1.34 1.06,1.06 C1.34,0.78 1.5,0.4 1.5,0 C1.5,-0.3 1.41,-0.59 1.25,-0.83 C1.08,-1.08 0.85,-1.27 0.57,-1.39 C0.3,-1.5 0,-1.53 -0.29,-1.47 C-0.58,-1.41 -0.85,-1.27 -1.06,-1.06 C-1.27,-0.85 -1.41,-0.58 -1.47,-0.29 C-1.53,0 -1.5,0.3 -1.39,0.57 C-1.27,0.85 -1.08,1.08 -0.83,1.25c M2.06 -2.82 C2.06,-2.82 4.35,-3.64 4.35,-3.64 C6.99,-4.84 10,-3 10,1.39 C10,1.96 9.83,2.5 9.49,2.95 C9.16,3.41 8.69,3.74 8.15,3.9 C7.62,4.06 7.04,4.05 6.51,3.86 C5.99,3.67 5.54,3.31 5.23,2.84 C4.75,2.13 4.01,1.64 3.16,1.48 C3.07,1.68 2.95,1.87 2.82,2.06 C2.82,2.06 3.64,4.35 3.64,4.35 C4.84,6.99 3.01,10 -1.39,10 C-1.95,10 -2.5,9.83 -2.95,9.49 C-3.41,9.16 -3.74,8.69 -3.9,8.15 C-4.06,7.62 -4.05,7.04 -3.86,6.51 C-3.67,5.99 -3.31,5.54 -2.84,5.23 C-2.13,4.75 -1.64,4.01 -1.47,3.16 C-1.68,3.07 -1.87,2.95 -2.06,2.82 C-2.06,2.82 -4.34,3.64 -4.34,3.64 C-6.99,4.84 -10,3.01 -10,-1.39 C-10,-1.95 -9.83,-2.5 -9.49,-2.95 C-9.16,-3.41 -8.69,-3.74 -8.15,-3.9 C-7.62,-4.06 -7.04,-4.05 -6.51,-3.86 C-5.99,-3.66 -5.53,-3.31 -5.23,-2.84 C-4.75,-2.13 -4,-1.64 -3.16,-1.47 C-3.07,-1.68 -2.95,-1.87 -2.82,-2.06 C-2.82,-2.06 -3.64,-4.34 -3.64,-4.34 C-4.84,-6.99 -3.01,-10 1.39,-10 C1.96,-10 2.5,-9.83 2.95,-9.49 C3.41,-9.16 3.74,-8.69 3.9,-8.15 C4.06,-7.62 4.05,-7.04 3.86,-6.51 C3.67,-5.99 3.31,-5.53 2.84,-5.23 C2.13,-4.75 1.64,-4 1.47,-3.16 C1.68,-3.07 1.87,-2.95 2.06,-2.82c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G_N_2_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="rotation" android:duration="500" android:startOffset="0" android:valueFrom="180" android:valueTo="360" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M0.25 -12 C-6.37,-12.14 -11.86,-6.88 -12,-0.25 C-12.14,6.37 -6.88,11.86 -0.25,12 C6.37,12.14 11.86,6.88 12,0.25 C12.14,-6.37 6.88,-11.86 0.25,-12c " android:valueTo="M0.03 -1.6 C-0.85,-1.62 -1.58,-0.92 -1.6,-0.03 C-1.62,0.85 -0.92,1.58 -0.03,1.6 C0.85,1.62 1.58,0.92 1.6,0.03 C1.62,-0.85 0.92,-1.58 0.03,-1.6c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="rotation" android:duration="500" android:startOffset="0" android:valueFrom="180" android:valueTo="360" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="500" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="767" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_fan_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_fan_on_anim.xml new file mode 100644 index 000000000000..5987b076ca70 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_fan_on_anim.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12" android:translateY="12" android:rotation="180"> + <group android:name="_R_G_L_1_G" android:rotation="360"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M5.4 0.25 C5.99,0.64 6.5,1.14 6.89,1.73 C6.89,1.73 6.89,1.73 6.89,1.73 C6.96,1.84 7.07,1.93 7.19,1.97 C7.31,2.02 7.45,2.03 7.57,1.99 C7.7,1.95 7.81,1.87 7.89,1.76 C7.97,1.66 8,1.53 8,1.39 C8.07,0.81 7.99,0.22 7.78,-0.33 C7.57,-0.88 7.23,-1.37 6.78,-1.76 C6.54,-1.91 6.27,-1.99 5.99,-2 C5.71,-2.01 5.42,-1.95 5.17,-1.82 C5.17,-1.82 3.29,-1.14 3.29,-1.14 C3.36,-0.94 3.42,-0.73 3.45,-0.52 C4.14,-0.4 4.81,-0.14 5.4,0.25c M0.33 7.78 C0.88,7.57 1.37,7.22 1.76,6.78 C1.76,6.78 1.76,6.78 1.76,6.78 C1.9,6.54 1.99,6.27 2,5.99 C2.01,5.71 1.95,5.42 1.82,5.17 C1.82,5.17 1.14,3.29 1.14,3.29 C0.94,3.36 0.73,3.42 0.52,3.45 C0.4,4.14 0.13,4.81 -0.25,5.4 C-0.64,5.99 -1.14,6.5 -1.73,6.89 C-1.84,6.96 -1.93,7.07 -1.97,7.19 C-2.02,7.31 -2.02,7.45 -1.99,7.57 C-1.95,7.7 -1.87,7.81 -1.76,7.89 C-1.66,7.97 -1.53,8 -1.39,8 C-0.81,8.07 -0.22,7.99 0.33,7.78c M-5.99 2 C-5.7,2.01 -5.42,1.95 -5.17,1.82 C-5.17,1.82 -3.29,1.14 -3.29,1.14 C-3.36,0.94 -3.42,0.73 -3.45,0.52 C-4.14,0.4 -4.81,0.14 -5.4,-0.25 C-5.99,-0.64 -6.5,-1.14 -6.89,-1.73 C-6.96,-1.84 -7.06,-1.93 -7.19,-1.97 C-7.31,-2.02 -7.45,-2.02 -7.57,-1.99 C-7.7,-1.95 -7.81,-1.87 -7.89,-1.76 C-7.96,-1.66 -8,-1.53 -8,-1.39 C-8.07,-0.81 -7.99,-0.22 -7.78,0.33 C-7.57,0.88 -7.23,1.37 -6.78,1.75 C-6.54,1.9 -6.27,1.99 -5.99,2c M-0.33 -7.78 C-0.88,-7.57 -1.37,-7.23 -1.75,-6.78 C-1.9,-6.54 -1.99,-6.27 -2,-5.99 C-2.01,-5.7 -1.95,-5.42 -1.82,-5.17 C-1.82,-5.17 -1.14,-3.29 -1.14,-3.29 C-0.94,-3.36 -0.73,-3.41 -0.52,-3.45 C-0.4,-4.14 -0.13,-4.81 0.25,-5.4 C0.64,-5.99 1.14,-6.5 1.73,-6.89 C1.84,-6.96 1.93,-7.06 1.97,-7.19 C2.02,-7.31 2.03,-7.45 1.99,-7.57 C1.95,-7.7 1.87,-7.81 1.76,-7.89 C1.66,-7.96 1.53,-8 1.39,-8 C0.81,-8.07 0.22,-7.99 -0.33,-7.78c M-0.83 1.25 C-0.59,1.41 -0.3,1.5 0,1.5 C0.4,1.5 0.78,1.34 1.06,1.06 C1.34,0.78 1.5,0.4 1.5,0 C1.5,-0.3 1.41,-0.59 1.25,-0.83 C1.08,-1.08 0.85,-1.27 0.57,-1.39 C0.3,-1.5 0,-1.53 -0.29,-1.47 C-0.58,-1.41 -0.85,-1.27 -1.06,-1.06 C-1.27,-0.85 -1.41,-0.58 -1.47,-0.29 C-1.53,0 -1.5,0.3 -1.39,0.57 C-1.27,0.85 -1.08,1.08 -0.83,1.25c M2.06 -2.82 C2.06,-2.82 4.35,-3.64 4.35,-3.64 C6.99,-4.84 10,-3 10,1.39 C10,1.96 9.83,2.5 9.49,2.95 C9.16,3.41 8.69,3.74 8.15,3.9 C7.62,4.06 7.04,4.05 6.51,3.86 C5.99,3.67 5.54,3.31 5.23,2.84 C4.75,2.13 4.01,1.64 3.16,1.48 C3.07,1.68 2.95,1.87 2.82,2.06 C2.82,2.06 3.64,4.35 3.64,4.35 C4.84,6.99 3.01,10 -1.39,10 C-1.95,10 -2.5,9.83 -2.95,9.49 C-3.41,9.16 -3.74,8.69 -3.9,8.15 C-4.06,7.62 -4.05,7.04 -3.86,6.51 C-3.67,5.99 -3.31,5.54 -2.84,5.23 C-2.13,4.75 -1.64,4.01 -1.47,3.16 C-1.68,3.07 -1.87,2.95 -2.06,2.82 C-2.06,2.82 -4.34,3.64 -4.34,3.64 C-6.99,4.84 -10,3.01 -10,-1.39 C-10,-1.95 -9.83,-2.5 -9.49,-2.95 C-9.16,-3.41 -8.69,-3.74 -8.15,-3.9 C-7.62,-4.06 -7.04,-4.05 -6.51,-3.86 C-5.99,-3.66 -5.53,-3.31 -5.23,-2.84 C-4.75,-2.13 -4,-1.64 -3.16,-1.47 C-3.07,-1.68 -2.95,-1.87 -2.82,-2.06 C-2.82,-2.06 -3.64,-4.34 -3.64,-4.34 C-4.84,-6.99 -3.01,-10 1.39,-10 C1.96,-10 2.5,-9.83 2.95,-9.49 C3.41,-9.16 3.74,-8.69 3.9,-8.15 C4.06,-7.62 4.05,-7.04 3.86,-6.51 C3.67,-5.99 3.31,-5.53 2.84,-5.23 C2.13,-4.75 1.64,-4 1.47,-3.16 C1.68,-3.07 1.87,-2.95 2.06,-2.82c "/> + </group> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12" android:rotation="180"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M0.03 -1.6 C-0.85,-1.62 -1.58,-0.92 -1.6,-0.03 C-1.62,0.85 -0.92,1.58 -0.03,1.6 C0.85,1.62 1.58,0.92 1.6,0.03 C1.62,-0.85 0.92,-1.58 0.03,-1.6c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.83 1.25 C-0.59,1.41 -0.3,1.5 0,1.5 C0.4,1.5 0.78,1.34 1.06,1.06 C1.34,0.78 1.5,0.4 1.5,0 C1.5,-0.3 1.41,-0.59 1.25,-0.83 C1.08,-1.08 0.85,-1.27 0.57,-1.39 C0.3,-1.5 0,-1.53 -0.29,-1.47 C-0.58,-1.41 -0.85,-1.27 -1.06,-1.06 C-1.27,-0.85 -1.41,-0.58 -1.47,-0.29 C-1.53,0 -1.5,0.3 -1.39,0.57 C-1.27,0.85 -1.08,1.08 -0.83,1.25c M2.06 -2.82 C2.06,-2.82 4.35,-3.64 4.35,-3.64 C6.99,-4.84 10,-3 10,1.39 C10,1.96 9.83,2.5 9.49,2.95 C9.16,3.41 8.69,3.74 8.15,3.9 C7.62,4.06 7.04,4.05 6.51,3.86 C5.99,3.67 5.54,3.31 5.23,2.84 C4.75,2.13 4.01,1.64 3.16,1.48 C3.07,1.68 2.95,1.87 2.82,2.06 C2.82,2.06 3.64,4.35 3.64,4.35 C4.84,6.99 3.01,10 -1.39,10 C-1.95,10 -2.5,9.83 -2.95,9.49 C-3.41,9.16 -3.74,8.69 -3.9,8.15 C-4.06,7.62 -4.05,7.04 -3.86,6.51 C-3.67,5.99 -3.31,5.54 -2.84,5.23 C-2.13,4.75 -1.64,4.01 -1.47,3.16 C-1.68,3.07 -1.87,2.95 -2.06,2.82 C-2.06,2.82 -4.34,3.64 -4.34,3.64 C-6.99,4.84 -10,3.01 -10,-1.39 C-10,-1.95 -9.83,-2.5 -9.49,-2.95 C-9.16,-3.41 -8.69,-3.74 -8.15,-3.9 C-7.62,-4.06 -7.04,-4.05 -6.51,-3.86 C-5.99,-3.66 -5.53,-3.31 -5.23,-2.84 C-4.75,-2.13 -4,-1.64 -3.16,-1.47 C-3.07,-1.68 -2.95,-1.87 -2.82,-2.06 C-2.82,-2.06 -3.64,-4.34 -3.64,-4.34 C-4.84,-6.99 -3.01,-10 1.39,-10 C1.96,-10 2.5,-9.83 2.95,-9.49 C3.41,-9.16 3.74,-8.69 3.9,-8.15 C4.06,-7.62 4.05,-7.04 3.86,-6.51 C3.67,-5.99 3.31,-5.53 2.84,-5.23 C2.13,-4.75 1.64,-4 1.47,-3.16 C1.68,-3.07 1.87,-2.95 2.06,-2.82c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="rotation" android:duration="500" android:startOffset="0" android:valueFrom="180" android:valueTo="360" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M0.03 -1.6 C-0.85,-1.62 -1.58,-0.92 -1.6,-0.03 C-1.62,0.85 -0.92,1.58 -0.03,1.6 C0.85,1.62 1.58,0.92 1.6,0.03 C1.62,-0.85 0.92,-1.58 0.03,-1.6c " android:valueTo="M0.25 -12 C-6.37,-12.14 -11.86,-6.88 -12,-0.25 C-12.14,6.37 -6.88,11.86 -0.25,12 C6.37,12.14 11.86,6.88 12,0.25 C12.14,-6.37 6.88,-11.86 0.25,-12c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="rotation" android:duration="500" android:startOffset="0" android:valueFrom="180" android:valueTo="360" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_garage.xml b/packages/SystemUI/res/drawable/ic_device_garage.xml new file mode 100644 index 000000000000..9a31f332fd3e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_garage.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_garage_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_garage_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_garage_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_garage_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_garage_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_garage_off_anim.xml new file mode 100644 index 000000000000..1a5bd286fde8 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_garage_off_anim.xml @@ -0,0 +1,290 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_6_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_6_G"> + <path android:name="_R_G_L_6_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 -9 C0,-9 8,-3 8,-3 C8,-3 8,9 8,9 C8,9 6,9 6,9 C6,9 6,-2 6,-2 C6,-2 0,-6.5 0,-6.5 C0,-6.5 -6,-2 -6,-2 C-6,-2 -6,9 -6,9 C-6,9 -8,9 -8,9 C-8,9 -8,-3 -8,-3 C-8,-3 0,-9 0,-9c "/> + </group> + </group> + <group android:name="_R_G_L_5_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_5_G" android:translateX="0" android:translateY="4"> + <group android:name="_R_G_L_5_C_0_G"> + <clip-path android:name="_R_G_L_5_C_0" android:pathData=" M5.14 -5.06 C5.14,-5.06 -5.12,-5.06 -5.12,-5.06 C-5.12,-5.06 -5.12,4.88 -5.12,4.88 C-5.12,4.88 5.14,4.88 5.14,4.88 C5.14,4.88 5.14,-5.06 5.14,-5.06c "/> + <group android:name="_R_G_L_5_C_0_G_G"> + <path android:name="_R_G_L_5_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3 -1 C3,-1 3,-3 3,-3 C3,-3 -3,-3 -3,-3 C-3,-3 -3,-1 -3,-1 C-3,-1 3,-1 3,-1c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c "/> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_4_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_4_G_N_7_T_0" android:translateX="0" android:translateY="4"> + <group android:name="_R_G_L_4_G" android:translateY="-8.125"> + <group android:name="_R_G_L_4_C_0_G"> + <clip-path android:name="_R_G_L_4_C_0" android:pathData=" M5.14 3.19 C5.14,3.19 -5.12,3.19 -5.12,3.19 C-5.12,3.19 -5.12,13.13 -5.12,13.13 C-5.12,13.13 5.14,13.13 5.14,13.13 C5.14,13.13 5.14,3.19 5.14,3.19c "/> + <group android:name="_R_G_L_4_C_0_G_G"> + <path android:name="_R_G_L_4_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3.35 -1.34 C3.35,-1.34 0.75,-1.44 0.75,-1.44 C0.75,-1.44 -0.62,-1.44 -0.62,-1.44 C-0.62,-1.44 -2.65,-1.34 -2.65,-1.34 C-2.65,-1.34 3.35,-1.34 3.35,-1.34c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_3_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_3_G_N_7_T_0" android:translateX="0" android:translateY="4"> + <group android:name="_R_G_L_3_G" android:translateX="0" android:translateY="-2"> + <group android:name="_R_G_L_3_C_0_G"> + <clip-path android:name="_R_G_L_3_C_0" android:pathData=" M4.96 -2.77 C4.96,-2.77 -4.87,-2.77 -4.87,-2.77 C-4.87,-2.77 -4.87,7.15 -4.87,7.15 C-4.87,7.15 4.96,7.15 4.96,7.15 C4.96,7.15 4.96,-2.77 4.96,-2.77c "/> + <group android:name="_R_G_L_3_C_0_G_G"> + <path android:name="_R_G_L_3_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_2_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_2_G_N_7_T_0" android:translateX="0" android:translateY="4"> + <group android:name="_R_G_L_2_G" android:translateX="0" android:translateY="2"> + <group android:name="_R_G_L_2_C_0_G"> + <clip-path android:name="_R_G_L_2_C_0" android:pathData=" M4.96 -6.95 C4.96,-6.95 -4.87,-6.95 -4.87,-6.95 C-4.87,-6.95 -4.87,2.97 -4.87,2.97 C-4.87,2.97 4.96,2.97 4.96,2.97 C4.96,2.97 4.96,-6.95 4.96,-6.95c "/> + <group android:name="_R_G_L_2_C_0_G_G"> + <path android:name="_R_G_L_2_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_1_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="0" android:translateY="4"> + <group android:name="_R_G_L_1_G" android:translateY="-6.062"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.75 -0.22 C-0.75,-0.22 1,-0.25 1,-0.25 C1,-0.25 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -0.75,-0.22 -0.75,-0.22c "/> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_G"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-8 -3 C-8,-3 0,-9 0,-9 C0,-9 8,-3 8,-3 C8,-3 8,9 8,9 C8,9 5,9 5,9 C5,9 5,-1 5,-1 C5,-1 -5,-1 -5,-1 C-5,-1 -5,9 -5,9 C-5,9 -8,9 -8,9 C-8,9 -8,-3 -8,-3c "/> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_6_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_5_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M5.14 -5.06 C5.14,-5.06 -5.12,-5.06 -5.12,-5.06 C-5.12,-5.06 -5.12,4.88 -5.12,4.88 C-5.12,4.88 5.14,4.88 5.14,4.88 C5.14,4.88 5.14,-5.06 5.14,-5.06c " android:valueTo="M5.14 -12.94 C5.14,-12.94 -5.12,-12.94 -5.12,-12.94 C-5.12,-12.94 -5.12,-3 -5.12,-3 C-5.12,-3 5.14,-3 5.14,-3 C5.14,-3 5.14,-12.94 5.14,-12.94c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_5_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,4C 0,4.281 0,10.998999999999999 0,12.062"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_5_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M5.14 3.19 C5.14,3.19 -5.12,3.19 -5.12,3.19 C-5.12,3.19 -5.12,13.13 -5.12,13.13 C-5.12,13.13 5.14,13.13 5.14,13.13 C5.14,13.13 5.14,3.19 5.14,3.19c " android:valueTo="M5.14 -4.94 C5.14,-4.94 -5.12,-4.94 -5.12,-4.94 C-5.12,-4.94 -5.12,5 -5.12,5 C-5.12,5 5.14,5 5.14,5 C5.14,5 5.14,-4.94 5.14,-4.94c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3.35 -1.34 C3.35,-1.34 0.75,-1.44 0.75,-1.44 C0.75,-1.44 -0.62,-1.44 -0.62,-1.44 C-0.62,-1.44 -2.65,-1.34 -2.65,-1.34 C-2.65,-1.34 3.35,-1.34 3.35,-1.34c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c " android:valueTo=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3 -1 C3,-1 3,-3 3,-3 C3,-3 -3,-3 -3,-3 C-3,-3 -3,-1 -3,-1 C-3,-1 3,-1 3,-1c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,4C 0,4.281 0,10.998999999999999 0,12.062"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M4.96 -2.77 C4.96,-2.77 -4.87,-2.77 -4.87,-2.77 C-4.87,-2.77 -4.87,7.15 -4.87,7.15 C-4.87,7.15 4.96,7.15 4.96,7.15 C4.96,7.15 4.96,-2.77 4.96,-2.77c " android:valueTo="M4.96 -7.02 C4.96,-7.02 -4.87,-7.02 -4.87,-7.02 C-4.87,-7.02 -4.87,2.9 -4.87,2.9 C-4.87,2.9 4.96,2.9 4.96,2.9 C4.96,2.9 4.96,-7.02 4.96,-7.02c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-2C 0,-1.844 0,-1.218 0,-1.062"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,4C 0,4.281 0,10.998999999999999 0,12.062"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M4.96 -6.95 C4.96,-6.95 -4.87,-6.95 -4.87,-6.95 C-4.87,-6.95 -4.87,2.97 -4.87,2.97 C-4.87,2.97 4.96,2.97 4.96,2.97 C4.96,2.97 4.96,-6.95 4.96,-6.95c " android:valueTo="M4.96 -16.33 C4.96,-16.33 -4.87,-16.33 -4.87,-16.33 C-4.87,-16.33 -4.87,-6.41 -4.87,-6.41 C-4.87,-6.41 4.96,-6.41 4.96,-6.41 C4.96,-6.41 4.96,-16.33 4.96,-16.33c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,2C 0,2.208 0,3.042 0,3.25"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,4C 0,4.281 0,10.998999999999999 0,12.062"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="317" android:startOffset="0" android:valueFrom="M-0.75 -0.22 C-0.75,-0.22 1,-0.25 1,-0.25 C1,-0.25 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -0.75,-0.22 -0.75,-0.22c " android:valueTo="M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,4C 0,4.281 0,10.998999999999999 0,12.062"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_garage_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_garage_on_anim.xml new file mode 100644 index 000000000000..a1999e03436d --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_garage_on_anim.xml @@ -0,0 +1,295 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_6_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_6_G"> + <path android:name="_R_G_L_6_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 -9 C0,-9 8,-3 8,-3 C8,-3 8,9 8,9 C8,9 6,9 6,9 C6,9 6,-2 6,-2 C6,-2 0,-6.5 0,-6.5 C0,-6.5 -6,-2 -6,-2 C-6,-2 -6,9 -6,9 C-6,9 -8,9 -8,9 C-8,9 -8,-3 -8,-3 C-8,-3 0,-9 0,-9c "/> + </group> + </group> + <group android:name="_R_G_L_5_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_5_G" android:translateX="0" android:translateY="12.062"> + <group android:name="_R_G_L_5_C_0_G"> + <clip-path android:name="_R_G_L_5_C_0" android:pathData=" M5.14 -12.94 C5.14,-12.94 -5.12,-12.94 -5.12,-12.94 C-5.12,-12.94 -5.12,-3 -5.12,-3 C-5.12,-3 5.14,-3 5.14,-3 C5.14,-3 5.14,-12.94 5.14,-12.94c "/> + <group android:name="_R_G_L_5_C_0_G_G"> + <path android:name="_R_G_L_5_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3 -1 C3,-1 3,-3 3,-3 C3,-3 -3,-3 -3,-3 C-3,-3 -3,-1 -3,-1 C-3,-1 3,-1 3,-1c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c "/> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_4_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_4_G_N_7_T_0" android:translateX="0" android:translateY="12.062"> + <group android:name="_R_G_L_4_G" android:translateY="-8.125"> + <group android:name="_R_G_L_4_C_0_G"> + <clip-path android:name="_R_G_L_4_C_0" android:pathData=" M5.14 -4.94 C5.14,-4.94 -5.12,-4.94 -5.12,-4.94 C-5.12,-4.94 -5.12,5 -5.12,5 C-5.12,5 5.14,5 5.14,5 C5.14,5 5.14,-4.94 5.14,-4.94c "/> + <group android:name="_R_G_L_4_C_0_G_G"> + <path android:name="_R_G_L_4_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3 -1 C3,-1 3,-3 3,-3 C3,-3 -3,-3 -3,-3 C-3,-3 -3,-1 -3,-1 C-3,-1 3,-1 3,-1c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_3_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_3_G_N_7_T_0" android:translateX="0" android:translateY="12.062"> + <group android:name="_R_G_L_3_G" android:translateX="0" android:translateY="-1.062"> + <group android:name="_R_G_L_3_C_0_G"> + <clip-path android:name="_R_G_L_3_C_0" android:pathData=" M4.96 -7.02 C4.96,-7.02 -4.87,-7.02 -4.87,-7.02 C-4.87,-7.02 -4.87,2.9 -4.87,2.9 C-4.87,2.9 4.96,2.9 4.96,2.9 C4.96,2.9 4.96,-7.02 4.96,-7.02c "/> + <group android:name="_R_G_L_3_C_0_G_G"> + <path android:name="_R_G_L_3_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_2_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_2_G_N_7_T_0" android:translateX="0" android:translateY="12.062"> + <group android:name="_R_G_L_2_G" android:translateX="0" android:translateY="3.25"> + <group android:name="_R_G_L_2_C_0_G"> + <clip-path android:name="_R_G_L_2_C_0" android:pathData=" M4.96 -16.33 C4.96,-16.33 -4.87,-16.33 -4.87,-16.33 C-4.87,-16.33 -4.87,-6.41 -4.87,-6.41 C-4.87,-6.41 4.96,-6.41 4.96,-6.41 C4.96,-6.41 4.96,-16.33 4.96,-16.33c "/> + <group android:name="_R_G_L_2_C_0_G_G"> + <path android:name="_R_G_L_2_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_1_G_N_7_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="0" android:translateY="12.062"> + <group android:name="_R_G_L_1_G" android:translateY="-6.062"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c "/> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_0_G"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-8 -3 C-8,-3 0,-9 0,-9 C0,-9 8,-3 8,-3 C8,-3 8,9 8,9 C8,9 5,9 5,9 C5,9 5,-1 5,-1 C5,-1 -5,-1 -5,-1 C-5,-1 -5,9 -5,9 C-5,9 -8,9 -8,9 C-8,9 -8,-3 -8,-3c "/> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_6_G_N_1_T_0"> + + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_5_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M5.14 -12.94 C5.14,-12.94 -5.12,-12.94 -5.12,-12.94 C-5.12,-12.94 -5.12,-3 -5.12,-3 C-5.12,-3 5.14,-3 5.14,-3 C5.14,-3 5.14,-12.94 5.14,-12.94c " android:valueTo="M5.14 -5.06 C5.14,-5.06 -5.12,-5.06 -5.12,-5.06 C-5.12,-5.06 -5.12,4.88 -5.12,4.88 C-5.12,4.88 5.14,4.88 5.14,4.88 C5.14,4.88 5.14,-5.06 5.14,-5.06c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_5_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,12.062C 0,10.998999999999999 0,4.281 0,4"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_5_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M5.14 -4.94 C5.14,-4.94 -5.12,-4.94 -5.12,-4.94 C-5.12,-4.94 -5.12,5 -5.12,5 C-5.12,5 5.14,5 5.14,5 C5.14,5 5.14,-4.94 5.14,-4.94c " android:valueTo="M5.14 3.19 C5.14,3.19 -5.12,3.19 -5.12,3.19 C-5.12,3.19 -5.12,13.13 -5.12,13.13 C-5.12,13.13 5.14,13.13 5.14,13.13 C5.14,13.13 5.14,3.19 5.14,3.19c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3 -1 C3,-1 3,-3 3,-3 C3,-3 -3,-3 -3,-3 C-3,-3 -3,-1 -3,-1 C-3,-1 3,-1 3,-1c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c " android:valueTo=" M-3 1 C-3,1 -3,3 -3,3 C-3,3 3,3 3,3 C3,3 3,1 3,1 C3,1 -3,1 -3,1c M3.35 -1.34 C3.35,-1.34 0.75,-1.44 0.75,-1.44 C0.75,-1.44 -0.62,-1.44 -0.62,-1.44 C-0.62,-1.44 -2.65,-1.34 -2.65,-1.34 C-2.65,-1.34 3.35,-1.34 3.35,-1.34c M-5 5 C-5,5 -5,-5 -5,-5 C-5,-5 5,-5 5,-5 C5,-5 5,5 5,5 C5,5 -5,5 -5,5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,12.062C 0,10.998999999999999 0,4.281 0,4"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M4.96 -7.02 C4.96,-7.02 -4.87,-7.02 -4.87,-7.02 C-4.87,-7.02 -4.87,2.9 -4.87,2.9 C-4.87,2.9 4.96,2.9 4.96,2.9 C4.96,2.9 4.96,-7.02 4.96,-7.02c " android:valueTo="M4.96 -2.77 C4.96,-2.77 -4.87,-2.77 -4.87,-2.77 C-4.87,-2.77 -4.87,7.15 -4.87,7.15 C-4.87,7.15 4.96,7.15 4.96,7.15 C4.96,7.15 4.96,-2.77 4.96,-2.77c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,-1.062C 0,-1.218 0,-1.844 0,-2"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,12.062C 0,10.998999999999999 0,4.281 0,4"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="517" android:startOffset="0" android:valueFrom="M4.96 -16.33 C4.96,-16.33 -4.87,-16.33 -4.87,-16.33 C-4.87,-16.33 -4.87,-6.41 -4.87,-6.41 C-4.87,-6.41 4.96,-6.41 4.96,-6.41 C4.96,-6.41 4.96,-16.33 4.96,-16.33c " android:valueTo="M4.96 -6.95 C4.96,-6.95 -4.87,-6.95 -4.87,-6.95 C-4.87,-6.95 -4.87,2.97 -4.87,2.97 C-4.87,2.97 4.96,2.97 4.96,2.97 C4.96,2.97 4.96,-6.95 4.96,-6.95c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,3.25C 0,3.042 0,2.208 0,2"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,12.062C 0,10.998999999999999 0,4.281 0,4"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="0" android:valueFrom="M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c " android:valueTo="M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="317" android:startOffset="200" android:valueFrom="M-3 -1 C-3,-1 3,-1 3,-1 C3,-1 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -3,-1 -3,-1c " android:valueTo="M-0.75 -0.22 C-0.75,-0.22 1,-0.25 1,-0.25 C1,-0.25 3,1 3,1 C3,1 -3,1 -3,1 C-3,1 -0.75,-0.22 -0.75,-0.22c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_7_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="517" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,12.062C 0,10.998999999999999 0,4.281 0,4"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_7_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="250" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_gate.xml b/packages/SystemUI/res/drawable/ic_device_gate.xml new file mode 100644 index 000000000000..8fbf08bfeb48 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_gate.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_gate_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_gate_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_hood.xml b/packages/SystemUI/res/drawable/ic_device_hood.xml new file mode 100644 index 000000000000..e376db872884 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_hood.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_hood_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_hood_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_kettle.xml b/packages/SystemUI/res/drawable/ic_device_kettle.xml new file mode 100644 index 000000000000..81ea3901e9de --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_kettle.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_kettle_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_kettle_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_light.xml b/packages/SystemUI/res/drawable/ic_device_light.xml new file mode 100644 index 000000000000..ebd6c18b9699 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_light.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_light_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_light_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_light_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_light_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_light_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_light_off_anim.xml new file mode 100644 index 000000000000..213aa4e4413a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_light_off_anim.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.41 21.41 C13.04,21.79 12.53,22 12,22 C11.47,22 10.96,21.79 10.59,21.41 C10.21,21.04 10,20.53 10,20 C10,20 14,20 14,20 C14,20.53 13.79,21.04 13.41,21.41c "/> + <path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8 17 C8,17 16,17 16,17 C16,17 16,19 16,19 C16,19 8,19 8,19 C8,19 8,17 8,17c "/> + <path android:name="_R_G_L_1_G_D_2_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8.85 14 C8.85,14 15.15,14 15.15,14 C15.15,14 15.15,14 15.15,14 C15.88,13.5 16.47,12.83 16.88,12.04 C17.29,11.26 17.5,10.39 17.5,9.5 C17.5,8.04 16.92,6.64 15.89,5.61 C14.85,4.58 13.46,4 12,4 C10.54,4 9.14,4.58 8.11,5.61 C7.08,6.64 6.5,8.04 6.5,9.5 C6.49,10.39 6.7,11.26 7.11,12.04 C7.52,12.83 8.12,13.5 8.85,14c M7.44 3.56 C8.75,2.55 10.35,2 12,2 C12,2 12,2 12,2 C13.65,2 15.26,2.55 16.56,3.56 C17.87,4.56 18.81,5.97 19.24,7.57 C19.66,9.16 19.55,10.86 18.92,12.38 C18.28,13.9 17.16,15.18 15.73,16 C15.73,16 8.27,16 8.27,16 C6.84,15.18 5.72,13.9 5.09,12.38 C4.45,10.86 4.34,9.16 4.76,7.57 C5.19,5.97 6.13,4.56 7.44,3.56c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateY="0.25" android:pivotX="11.996" android:pivotY="14" android:scaleX="1.1" android:scaleY="1.1"> + <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8.85 14 C8.85,14 15.15,14 15.15,14 C15.15,14 15.15,14 15.15,14 C15.88,13.5 16.47,12.83 16.88,12.04 C17.29,11.26 17.5,10.39 17.5,9.5 C17.5,8.04 16.92,6.64 15.89,5.61 C14.85,4.58 13.46,4 12,4 C10.54,4 9.14,4.58 8.11,5.61 C7.08,6.64 6.5,8.04 6.5,9.5 C6.49,10.39 6.7,11.26 7.11,12.04 C7.52,12.83 8.12,13.5 8.85,14c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleX" android:duration="417" android:startOffset="0" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleY" android:duration="417" android:startOffset="0" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="417" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_light_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_light_on_anim.xml new file mode 100644 index 000000000000..bb9c58bf9958 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_light_on_anim.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G" android:translateY="0.25" android:pivotX="11.996" android:pivotY="14" android:scaleX="0" android:scaleY="0"> + <path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8.85 14 C8.85,14 15.15,14 15.15,14 C15.15,14 15.15,14 15.15,14 C15.88,13.5 16.47,12.83 16.88,12.04 C17.29,11.26 17.5,10.39 17.5,9.5 C17.5,8.04 16.92,6.64 15.89,5.61 C14.85,4.58 13.46,4 12,4 C10.54,4 9.14,4.58 8.11,5.61 C7.08,6.64 6.5,8.04 6.5,9.5 C6.49,10.39 6.7,11.26 7.11,12.04 C7.52,12.83 8.12,13.5 8.85,14c "/> + </group> + <group android:name="_R_G_L_0_G"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.41 21.41 C13.04,21.79 12.53,22 12,22 C11.47,22 10.96,21.79 10.59,21.41 C10.21,21.04 10,20.53 10,20 C10,20 14,20 14,20 C14,20.53 13.79,21.04 13.41,21.41c "/> + <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8 17 C8,17 16,17 16,17 C16,17 16,19 16,19 C16,19 8,19 8,19 C8,19 8,17 8,17c "/> + <path android:name="_R_G_L_0_G_D_2_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8.85 14 C8.85,14 15.15,14 15.15,14 C15.15,14 15.15,14 15.15,14 C15.88,13.5 16.47,12.83 16.88,12.04 C17.29,11.26 17.5,10.39 17.5,9.5 C17.5,8.04 16.92,6.64 15.89,5.61 C14.85,4.58 13.46,4 12,4 C10.54,4 9.14,4.58 8.11,5.61 C7.08,6.64 6.5,8.04 6.5,9.5 C6.49,10.39 6.7,11.26 7.11,12.04 C7.52,12.83 8.12,13.5 8.85,14c M7.44 3.56 C8.75,2.55 10.35,2 12,2 C12,2 12,2 12,2 C13.65,2 15.26,2.55 16.56,3.56 C17.87,4.56 18.81,5.97 19.24,7.57 C19.66,9.16 19.55,10.86 18.92,12.38 C18.28,13.9 17.16,15.18 15.73,16 C15.73,16 8.27,16 8.27,16 C6.84,15.18 5.72,13.9 5.09,12.38 C4.45,10.86 4.34,9.16 4.76,7.57 C5.19,5.97 6.13,4.56 7.44,3.56c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleX" android:duration="417" android:startOffset="0" android:valueFrom="0" android:valueTo="1.1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleY" android:duration="417" android:startOffset="0" android:valueFrom="0" android:valueTo="1.1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_lock.xml b/packages/SystemUI/res/drawable/ic_device_lock.xml new file mode 100644 index 000000000000..d291ba452852 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_lock.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_lock_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_lock_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_lock_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_lock_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_lock_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_lock_off_anim.xml new file mode 100644 index 000000000000..321bf1033fec --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_lock_off_anim.xml @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="12.008" android:translateY="11.992"> + <group android:name="_R_G_L_2_G" android:translateY="-0.5"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-3.48 -3.1,-3.47 C-3.1,-3.47 -5,-3.47 -5,-3.47 C-5,-3.48 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c "/> + </group> + </group> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12.008" android:translateY="11.992" android:scaleY="0"> + <group android:name="_R_G_L_1_G" android:translateY="-0.5"> + <group android:name="_R_G_L_1_C_0_G"> + <clip-path android:name="_R_G_L_1_C_0" android:pathData=" M0 -4.8 C-4.6,-4.8 -8.32,-1.09 -8.32,3.5 C-8.32,8.08 -4.6,11.8 0,11.8 C4.59,11.8 8.32,8.08 8.32,3.5 C8.32,-1.09 4.59,-4.8 0,-4.8c "/> + <group android:name="_R_G_L_1_C_0_G_G"> + <path android:name="_R_G_L_1_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 5,-3.5 5,-3.5c "/> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12.008" android:translateY="11.992"> + <group android:name="_R_G_L_0_G" android:translateX="-0.006" android:translateY="-0.5"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M7.6 -2.1 C7.6,-2.1 -7.42,-2.1 -7.42,-2.1 C-7.42,-2.1 -7.42,9.61 -7.42,9.61 C-7.42,9.61 7.6,9.61 7.6,9.61 C7.6,9.61 7.6,-2.1 7.6,-2.1c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.11 5.16 C-0.78,5.38 -0.4,5.5 0,5.5 C0,5.5 0,5.5 0,5.5 C0.53,5.5 1.04,5.29 1.41,4.91 C1.79,4.54 2,4.03 2,3.5 C2,3.1 1.88,2.72 1.66,2.39 C1.44,2.06 1.13,1.8 0.77,1.65 C0.4,1.5 0,1.46 -0.39,1.54 C-0.78,1.62 -1.13,1.81 -1.41,2.09 C-1.69,2.37 -1.88,2.72 -1.96,3.11 C-2.04,3.5 -2,3.9 -1.85,4.26 C-1.7,4.63 -1.44,4.94 -1.11,5.16c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="0" android:valueFrom=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-3.48 -3.1,-3.47 C-3.1,-3.47 -5,-3.47 -5,-3.47 C-5,-3.48 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueTo=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-3.48 -3.1,-3.47 C-3.1,-3.47 -5,-3.47 -5,-3.47 C-5,-3.48 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="217" android:startOffset="283" android:valueFrom=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-3.48 -3.1,-3.47 C-3.1,-3.47 -5,-3.47 -5,-3.47 C-5,-3.48 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueTo=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-5.51 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-5.51 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="211" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,11.992C 12.008,12.159 12.008,12.992 12.008,12.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="106" android:startOffset="211" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,12.992C 12.008,12.992 12.008,12.159 12.008,11.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="0" android:valueFrom="M0 -4.8 C-4.6,-4.8 -8.32,-1.09 -8.32,3.5 C-8.32,8.08 -4.6,11.8 0,11.8 C4.59,11.8 8.32,8.08 8.32,3.5 C8.32,-1.09 4.59,-4.8 0,-4.8c " android:valueTo="M0 -4.8 C-4.6,-4.8 -8.32,-1.09 -8.32,3.5 C-8.32,8.08 -4.6,11.8 0,11.8 C4.59,11.8 8.32,8.08 8.32,3.5 C8.32,-1.09 4.59,-4.8 0,-4.8c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="300" android:startOffset="200" android:valueFrom="M0 -4.8 C-4.6,-4.8 -8.32,-1.09 -8.32,3.5 C-8.32,8.08 -4.6,11.8 0,11.8 C4.59,11.8 8.32,8.08 8.32,3.5 C8.32,-1.09 4.59,-4.8 0,-4.8c " android:valueTo="M0 1.5 C-1.11,1.5 -2,2.4 -2,3.5 C-2,4.6 -1.11,5.49 0,5.49 C1.1,5.49 2,4.6 2,3.5 C2,2.4 1.1,1.5 0,1.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="211" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,11.992C 12.008,12.159 12.008,12.992 12.008,12.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="106" android:startOffset="211" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,12.992C 12.008,12.992 12.008,12.159 12.008,11.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="200" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="300" android:startOffset="0" android:valueFrom="M-1.11 5.16 C-0.78,5.38 -0.4,5.5 0,5.5 C0,5.5 0,5.5 0,5.5 C0.53,5.5 1.04,5.29 1.41,4.91 C1.79,4.54 2,4.03 2,3.5 C2,3.1 1.88,2.72 1.66,2.39 C1.44,2.06 1.13,1.8 0.77,1.65 C0.4,1.5 0,1.46 -0.39,1.54 C-0.78,1.62 -1.13,1.81 -1.41,2.09 C-1.69,2.37 -1.88,2.72 -1.96,3.11 C-2.04,3.5 -2,3.9 -1.85,4.26 C-1.7,4.63 -1.44,4.94 -1.11,5.16c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueTo="M-0.03 3.5 C-0.03,3.5 -0.02,3.5 -0.02,3.5 C-0.02,3.5 -0.02,3.5 -0.02,3.5 C-0.01,3.5 -0.01,3.5 -0.01,3.49 C0,3.49 0,3.49 0,3.48 C0,3.48 0,3.47 0,3.47 C0,3.47 -0.01,3.46 -0.01,3.46 C-0.02,3.46 -0.02,3.46 -0.02,3.46 C-0.03,3.46 -0.03,3.46 -0.03,3.47 C-0.04,3.47 -0.04,3.47 -0.04,3.48 C-0.04,3.48 -0.04,3.48 -0.04,3.49 C-0.04,3.49 -0.03,3.5 -0.03,3.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="211" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,11.992C 12.008,12.159 12.008,12.992 12.008,12.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="106" android:startOffset="211" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,12.992C 12.008,12.992 12.008,12.159 12.008,11.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="283" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_lock_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_lock_on_anim.xml new file mode 100644 index 000000000000..3c19a7b24794 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_lock_on_anim.xml @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="12.008" android:translateY="11.992"> + <group android:name="_R_G_L_2_G" android:translateY="-0.5"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-5.51 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-5.51 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c "/> + </group> + </group> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12.008" android:translateY="11.992"> + <group android:name="_R_G_L_1_G" android:translateY="-0.5"> + <group android:name="_R_G_L_1_C_0_G"> + <clip-path android:name="_R_G_L_1_C_0" android:pathData=" M0 1.5 C-1.11,1.5 -2,2.4 -2,3.5 C-2,4.6 -1.11,5.49 0,5.49 C1.1,5.49 2,4.6 2,3.5 C2,2.4 1.1,1.5 0,1.5c "/> + <group android:name="_R_G_L_1_C_0_G_G"> + <path android:name="_R_G_L_1_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 5,-3.5 5,-3.5c "/> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12.008" android:translateY="11.992" android:scaleY="0"> + <group android:name="_R_G_L_0_G" android:translateX="-0.006" android:translateY="-0.5"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M7.08 -2 C7.08,-2 -6.89,-2 -6.89,-2 C-6.89,-2 -6.89,9.51 -6.89,9.51 C-6.89,9.51 7.08,9.51 7.08,9.51 C7.08,9.51 7.08,-2 7.08,-2c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.03 3.5 C-0.03,3.5 -0.02,3.5 -0.02,3.5 C-0.02,3.5 -0.02,3.5 -0.02,3.5 C-0.01,3.5 -0.01,3.5 -0.01,3.49 C0,3.49 0,3.49 0,3.48 C0,3.48 0,3.47 0,3.47 C0,3.47 -0.01,3.46 -0.01,3.46 C-0.02,3.46 -0.02,3.46 -0.02,3.46 C-0.03,3.46 -0.03,3.46 -0.03,3.47 C-0.04,3.47 -0.04,3.47 -0.04,3.48 C-0.04,3.48 -0.04,3.48 -0.04,3.49 C-0.04,3.49 -0.03,3.5 -0.03,3.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c "/> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="217" android:startOffset="0" android:valueFrom=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-5.51 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-5.51 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueTo=" M-6 8.5 C-6,8.5 6,8.5 6,8.5 C6,8.5 6,-1.5 6,-1.5 C6,-1.5 -6,-1.5 -6,-1.5 C-6,-1.5 -6,8.5 -6,8.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-6.32 2.77,-7.11 2.19,-7.69 C1.61,-8.27 0.82,-8.6 0,-8.6 C-0.82,-8.6 -1.61,-8.27 -2.19,-7.69 C-2.76,-7.12 -3.09,-6.34 -3.1,-5.53 C-3.1,-5.52 -3.1,-3.48 -3.1,-3.47 C-3.1,-3.47 -5,-3.47 -5,-3.47 C-5,-3.48 -5,-5.52 -5,-5.54 C-4.99,-6.85 -4.46,-8.11 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="106" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,11.992C 12.008,12.159 12.008,12.992 12.008,12.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="211" android:startOffset="106" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,12.992C 12.008,12.992 12.008,12.159 12.008,11.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="300" android:startOffset="0" android:valueFrom="M0 1.5 C-1.11,1.5 -2,2.4 -2,3.5 C-2,4.6 -1.11,5.49 0,5.49 C1.1,5.49 2,4.6 2,3.5 C2,2.4 1.1,1.5 0,1.5c " android:valueTo="M0 -4.8 C-4.6,-4.8 -8.32,-1.09 -8.32,3.5 C-8.32,8.08 -4.6,11.8 0,11.8 C4.59,11.8 8.32,8.08 8.32,3.5 C8.32,-1.09 4.59,-4.8 0,-4.8c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="106" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,11.992C 12.008,12.159 12.008,12.992 12.008,12.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="211" android:startOffset="106" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,12.992C 12.008,12.992 12.008,12.159 12.008,11.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="217" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="0" android:valueFrom="M-0.03 3.5 C-0.03,3.5 -0.02,3.5 -0.02,3.5 C-0.02,3.5 -0.02,3.5 -0.02,3.5 C-0.01,3.5 -0.01,3.5 -0.01,3.49 C0,3.49 0,3.49 0,3.48 C0,3.48 0,3.47 0,3.47 C0,3.47 -0.01,3.46 -0.01,3.46 C-0.02,3.46 -0.02,3.46 -0.02,3.46 C-0.03,3.46 -0.03,3.46 -0.03,3.47 C-0.04,3.47 -0.04,3.47 -0.04,3.48 C-0.04,3.48 -0.04,3.48 -0.04,3.49 C-0.04,3.49 -0.03,3.5 -0.03,3.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueTo="M-0.03 3.5 C-0.03,3.5 -0.02,3.5 -0.02,3.5 C-0.02,3.5 -0.02,3.5 -0.02,3.5 C-0.01,3.5 -0.01,3.5 -0.01,3.49 C0,3.49 0,3.49 0,3.48 C0,3.48 0,3.47 0,3.47 C0,3.47 -0.01,3.46 -0.01,3.46 C-0.02,3.46 -0.02,3.46 -0.02,3.46 C-0.03,3.46 -0.03,3.46 -0.03,3.47 C-0.04,3.47 -0.04,3.47 -0.04,3.48 C-0.04,3.48 -0.04,3.48 -0.04,3.49 C-0.04,3.49 -0.03,3.5 -0.03,3.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="300" android:startOffset="200" android:valueFrom="M-0.03 3.5 C-0.03,3.5 -0.02,3.5 -0.02,3.5 C-0.02,3.5 -0.02,3.5 -0.02,3.5 C-0.01,3.5 -0.01,3.5 -0.01,3.49 C0,3.49 0,3.49 0,3.48 C0,3.48 0,3.47 0,3.47 C0,3.47 -0.01,3.46 -0.01,3.46 C-0.02,3.46 -0.02,3.46 -0.02,3.46 C-0.03,3.46 -0.03,3.46 -0.03,3.47 C-0.04,3.47 -0.04,3.47 -0.04,3.48 C-0.04,3.48 -0.04,3.48 -0.04,3.49 C-0.04,3.49 -0.03,3.5 -0.03,3.5c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueTo="M-1.11 5.16 C-0.78,5.38 -0.4,5.5 0,5.5 C0,5.5 0,5.5 0,5.5 C0.53,5.5 1.04,5.29 1.41,4.91 C1.79,4.54 2,4.03 2,3.5 C2,3.1 1.88,2.72 1.66,2.39 C1.44,2.06 1.13,1.8 0.77,1.65 C0.4,1.5 0,1.46 -0.39,1.54 C-0.78,1.62 -1.13,1.81 -1.41,2.09 C-1.69,2.37 -1.88,2.72 -1.96,3.11 C-2.04,3.5 -2,3.9 -1.85,4.26 C-1.7,4.63 -1.44,4.94 -1.11,5.16c M5 -3.5 C5,-3.5 6,-3.5 6,-3.5 C6,-3.5 6,-3.5 6,-3.5 C6.53,-3.5 7.04,-3.29 7.41,-2.91 C7.79,-2.54 8,-2.03 8,-1.5 C8,-1.5 8,8.5 8,8.5 C8,9.03 7.79,9.54 7.41,9.91 C7.04,10.29 6.53,10.5 6,10.5 C6,10.5 -6,10.5 -6,10.5 C-6.53,10.5 -7.04,10.29 -7.41,9.91 C-7.79,9.54 -8,9.03 -8,8.5 C-8,8.5 -8,-1.5 -8,-1.5 C-8,-2.03 -7.79,-2.54 -7.41,-2.91 C-7.04,-3.29 -6.53,-3.5 -6,-3.5 C-6,-3.5 3.1,-3.5 3.1,-3.5 C3.1,-3.5 3.1,-5.5 3.1,-5.5 C3.1,-5.91 3.02,-6.31 2.86,-6.69 C2.71,-7.06 2.48,-7.4 2.19,-7.69 C1.9,-7.98 1.56,-8.21 1.19,-8.36 C0.81,-8.52 0.41,-8.6 0,-8.6 C-0.41,-8.6 -0.81,-8.52 -1.19,-8.36 C-1.56,-8.21 -1.9,-7.98 -2.19,-7.69 C-2.48,-7.4 -2.71,-7.06 -2.86,-6.69 C-3.02,-6.31 -3.1,-5.91 -3.1,-5.5 C-3.1,-5.5 -5,-5.5 -5,-5.5 C-5,-6.83 -4.47,-8.1 -3.54,-9.04 C-2.6,-9.97 -1.33,-10.5 0,-10.5 C1.33,-10.5 2.6,-9.97 3.54,-9.04 C4.47,-8.1 5,-6.83 5,-5.5 C5,-5.5 5,-3.5 5,-3.5c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="106" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,11.992C 12.008,12.159 12.008,12.992 12.008,12.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateXY" android:duration="211" android:startOffset="106" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12.008,12.992C 12.008,12.992 12.008,12.159 12.008,11.992"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="217" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_microwave.xml b/packages/SystemUI/res/drawable/ic_device_microwave.xml new file mode 100644 index 000000000000..59d9284ac552 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_microwave.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_microwave_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_microwave_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_mop.xml b/packages/SystemUI/res/drawable/ic_device_mop.xml new file mode 100644 index 000000000000..7b36078c3198 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_mop.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_mop_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_mop_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_multicooker.xml b/packages/SystemUI/res/drawable/ic_device_multicooker.xml new file mode 100644 index 000000000000..8c9f60836eb5 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_multicooker.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_multicooker_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_multicooker_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_outdoor_garden.xml b/packages/SystemUI/res/drawable/ic_device_outdoor_garden.xml new file mode 100644 index 000000000000..a6cb2d8cbd04 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_outdoor_garden.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_outdoor_garden_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_outdoor_garden_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_outlet.xml b/packages/SystemUI/res/drawable/ic_device_outlet.xml new file mode 100644 index 000000000000..17f140e71ffa --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_outlet.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_outlet_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_outlet_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_outlet_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_outlet_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_outlet_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_outlet_off_anim.xml new file mode 100644 index 000000000000..85d645ebb383 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_outlet_off_anim.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_3_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_3_G" android:translateX="-4" android:translateY="-1"> + <path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -2 C-1,-2 1,-2 1,-2 C1,-2 1,2 1,2 C1,2 -1,2 -1,2 C-1,2 -1,-2 -1,-2c "/> + </group> + </group> + <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_2_G" android:translateY="4"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.71 -0.71 C-0.52,-0.89 -0.26,-1 0,-1 C0.27,-1 0.52,-0.89 0.71,-0.71 C0.9,-0.52 1,-0.26 1,0 C1,0 1,1 1,1 C1,1 -1,1 -1,1 C-1,1 -1,0 -1,0 C-1,-0.26 -0.89,-0.52 -0.71,-0.71c "/> + </group> + </group> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12" android:translateY="12" android:scaleY="0"> + <group android:name="_R_G_L_1_G" android:translateX="4" android:translateY="-1"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -2 C-1,-2 1,-2 1,-2 C1,-2 1,2 1,2 C1,2 -1,2 -1,2 C-1,2 -1,-2 -1,-2c "/> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_G"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 5 C-1,5 0,5 0,5 C0,5 1,5 1,5 C1,5 1,4.5 1,4.5 C1,4.5 1,4 1,4 C1,3.87 0.97,3.74 0.92,3.62 C0.87,3.5 0.8,3.39 0.71,3.29 C0.52,3.11 0.27,3 0,3 C-0.26,3 -0.52,3.11 -0.71,3.29 C-0.89,3.48 -1,3.74 -1,4 C-1,4 -1,5 -1,5c M-5.56 -8.31 C-3.91,-9.41 -1.98,-10 0,-10 C0,-10 0,-10 0,-10 C2.65,-10 5.2,-8.95 7.07,-7.07 C8.95,-5.2 10,-2.65 10,0 C10,1.98 9.41,3.91 8.32,5.56 C7.22,7.2 5.65,8.48 3.83,9.24 C2,10 -0.01,10.19 -1.95,9.81 C-3.89,9.42 -5.67,8.47 -7.07,7.07 C-8.47,5.67 -9.42,3.89 -9.81,1.95 C-10.19,0.01 -10,-2 -9.24,-3.83 C-8.48,-5.65 -7.2,-7.22 -5.56,-8.31c M3 1 C3,1 5,1 5,1 C5,1 5,-3 5,-3 C5,-3 3,-3 3,-3 C3,-3 3,1 3,1c M-5 1 C-5,1 -3,1 -3,1 C-3,1 -3,-3 -3,-3 C-3,-3 -5,-3 -5,-3 C-5,-3 -5,1 -5,1c "/> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_3_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="217" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="217" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="217" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M-1 5 C-1,5 0,5 0,5 C0,5 1,5 1,5 C1,5 1,4.5 1,4.5 C1,4.5 1,4 1,4 C1,3.87 0.97,3.74 0.92,3.62 C0.87,3.5 0.8,3.39 0.71,3.29 C0.52,3.11 0.27,3 0,3 C-0.26,3 -0.52,3.11 -0.71,3.29 C-0.89,3.48 -1,3.74 -1,4 C-1,4 -1,5 -1,5c M-5.56 -8.31 C-3.91,-9.41 -1.98,-10 0,-10 C0,-10 0,-10 0,-10 C2.65,-10 5.2,-8.95 7.07,-7.07 C8.95,-5.2 10,-2.65 10,0 C10,1.98 9.41,3.91 8.32,5.56 C7.22,7.2 5.65,8.48 3.83,9.24 C2,10 -0.01,10.19 -1.95,9.81 C-3.89,9.42 -5.67,8.47 -7.07,7.07 C-8.47,5.67 -9.42,3.89 -9.81,1.95 C-10.19,0.01 -10,-2 -9.24,-3.83 C-8.48,-5.65 -7.2,-7.22 -5.56,-8.31c M3 1 C3,1 5,1 5,1 C5,1 5,-3 5,-3 C5,-3 3,-3 3,-3 C3,-3 3,1 3,1c M-0.02 4.03 C-0.02,4.03 0.03,4.03 0.03,4.03 C0.03,4.03 0.03,4 0.03,4 C0.03,3.99 0.02,3.99 0.02,3.98 C0.01,3.98 0.01,3.98 0,3.98 C-0.01,3.98 -0.01,3.98 -0.02,3.98 C-0.02,3.99 -0.02,3.99 -0.02,4 C-0.02,4 -0.02,4.03 -0.02,4.03c M-5 1 C-5,1 -3,1 -3,1 C-3,1 -3,-3 -3,-3 C-3,-3 -5,-3 -5,-3 C-5,-3 -5,1 -5,1c " android:valueTo="M-4.44 6.65 C-3.13,7.53 -1.58,8 0,8 C2.12,8 4.16,7.16 5.66,5.66 C7.16,4.16 8,2.12 8,0 C8,-1.58 7.53,-3.13 6.65,-4.44 C5.77,-5.76 4.52,-6.79 3.06,-7.39 C1.6,-8 -0.01,-8.15 -1.56,-7.85 C-3.11,-7.54 -4.54,-6.78 -5.66,-5.66 C-6.78,-4.54 -7.54,-3.11 -7.85,-1.56 C-8.15,-0.01 -8,1.6 -7.39,3.06 C-6.79,4.52 -5.76,5.77 -4.44,6.65c M-5.56 -8.31 C-3.91,-9.41 -1.98,-10 0,-10 C0,-10 0,-10 0,-10 C2.65,-10 5.2,-8.95 7.07,-7.07 C8.95,-5.2 10,-2.65 10,0 C10,1.98 9.41,3.91 8.32,5.56 C7.22,7.2 5.65,8.48 3.83,9.24 C2,10 -0.01,10.19 -1.95,9.81 C-3.89,9.42 -5.67,8.47 -7.07,7.07 C-8.47,5.67 -9.42,3.89 -9.81,1.95 C-10.19,0.01 -10,-2 -9.24,-3.83 C-8.48,-5.65 -7.2,-7.22 -5.56,-8.31c M3 1 C3,1 5,1 5,1 C5,1 5,-3 5,-3 C5,-3 3,-3 3,-3 C3,-3 3,1 3,1c M-1 5 C-1,5 1,5 1,5 C1,5 1,4 1,4 C1,3.74 0.9,3.48 0.71,3.29 C0.52,3.11 0.27,3 0,3 C-0.26,3 -0.52,3.11 -0.71,3.29 C-0.89,3.48 -1,3.74 -1,4 C-1,4 -1,5 -1,5c M-5 1 C-5,1 -3,1 -3,1 C-3,1 -3,-3 -3,-3 C-3,-3 -5,-3 -5,-3 C-5,-3 -5,1 -5,1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_outlet_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_outlet_on_anim.xml new file mode 100644 index 000000000000..756f0282e9a4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_outlet_on_anim.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_3_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_3_G" android:translateX="-4" android:translateY="-1"> + <path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -2 C-1,-2 1,-2 1,-2 C1,-2 1,2 1,2 C1,2 -1,2 -1,2 C-1,2 -1,-2 -1,-2c "/> + </group> + </group> + <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_2_G" android:translateY="4"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.71 -0.71 C-0.52,-0.89 -0.26,-1 0,-1 C0.27,-1 0.52,-0.89 0.71,-0.71 C0.9,-0.52 1,-0.26 1,0 C1,0 1,1 1,1 C1,1 -1,1 -1,1 C-1,1 -1,0 -1,0 C-1,-0.26 -0.89,-0.52 -0.71,-0.71c "/> + </group> + </group> + <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_1_G" android:translateX="4" android:translateY="-1"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -2 C-1,-2 1,-2 1,-2 C1,-2 1,2 1,2 C1,2 -1,2 -1,2 C-1,2 -1,-2 -1,-2c "/> + </group> + </group> + <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_G"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4.44 6.65 C-3.13,7.53 -1.58,8 0,8 C2.12,8 4.16,7.16 5.66,5.66 C7.16,4.16 8,2.12 8,0 C8,-1.58 7.53,-3.13 6.65,-4.44 C5.77,-5.76 4.52,-6.79 3.06,-7.39 C1.6,-8 -0.01,-8.15 -1.56,-7.85 C-3.11,-7.54 -4.54,-6.78 -5.66,-5.66 C-6.78,-4.54 -7.54,-3.11 -7.85,-1.56 C-8.15,-0.01 -8,1.6 -7.39,3.06 C-6.79,4.52 -5.76,5.77 -4.44,6.65c M-5.56 -8.31 C-3.91,-9.41 -1.98,-10 0,-10 C0,-10 0,-10 0,-10 C2.65,-10 5.2,-8.95 7.07,-7.07 C8.95,-5.2 10,-2.65 10,0 C10,1.98 9.41,3.91 8.32,5.56 C7.22,7.2 5.65,8.48 3.83,9.24 C2,10 -0.01,10.19 -1.95,9.81 C-3.89,9.42 -5.67,8.47 -7.07,7.07 C-8.47,5.67 -9.42,3.89 -9.81,1.95 C-10.19,0.01 -10,-2 -9.24,-3.83 C-8.48,-5.65 -7.2,-7.22 -5.56,-8.31c M3 1 C3,1 5,1 5,1 C5,1 5,-3 5,-3 C5,-3 3,-3 3,-3 C3,-3 3,1 3,1c M-5 1 C-5,1 -3,1 -3,1 C-3,1 -3,-3 -3,-3 C-3,-3 -5,-3 -5,-3 C-5,-3 -5,1 -5,1c "/> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_3_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_3_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="100" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="100" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="100" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M-4.44 6.65 C-3.13,7.53 -1.58,8 0,8 C2.12,8 4.16,7.16 5.66,5.66 C7.16,4.16 8,2.12 8,0 C8,-1.58 7.53,-3.13 6.65,-4.44 C5.77,-5.76 4.52,-6.79 3.06,-7.39 C1.6,-8 -0.01,-8.15 -1.56,-7.85 C-3.11,-7.54 -4.54,-6.78 -5.66,-5.66 C-6.78,-4.54 -7.54,-3.11 -7.85,-1.56 C-8.15,-0.01 -8,1.6 -7.39,3.06 C-6.79,4.52 -5.76,5.77 -4.44,6.65c M-5.56 -8.31 C-3.91,-9.41 -1.98,-10 0,-10 C0,-10 0,-10 0,-10 C2.65,-10 5.2,-8.95 7.07,-7.07 C8.95,-5.2 10,-2.65 10,0 C10,1.98 9.41,3.91 8.32,5.56 C7.22,7.2 5.65,8.48 3.83,9.24 C2,10 -0.01,10.19 -1.95,9.81 C-3.89,9.42 -5.67,8.47 -7.07,7.07 C-8.47,5.67 -9.42,3.89 -9.81,1.95 C-10.19,0.01 -10,-2 -9.24,-3.83 C-8.48,-5.65 -7.2,-7.22 -5.56,-8.31c M3 1 C3,1 5,1 5,1 C5,1 5,-3 5,-3 C5,-3 3,-3 3,-3 C3,-3 3,1 3,1c M-1 5 C-1,5 1,5 1,5 C1,5 1,4 1,4 C1,3.74 0.9,3.48 0.71,3.29 C0.52,3.11 0.27,3 0,3 C-0.26,3 -0.52,3.11 -0.71,3.29 C-0.89,3.48 -1,3.74 -1,4 C-1,4 -1,5 -1,5c M-5 1 C-5,1 -3,1 -3,1 C-3,1 -3,-3 -3,-3 C-3,-3 -5,-3 -5,-3 C-5,-3 -5,1 -5,1c " android:valueTo="M-1 5 C-1,5 0,5 0,5 C0,5 1,5 1,5 C1,5 1,4.5 1,4.5 C1,4.5 1,4 1,4 C1,3.87 0.97,3.74 0.92,3.62 C0.87,3.5 0.8,3.39 0.71,3.29 C0.52,3.11 0.27,3 0,3 C-0.26,3 -0.52,3.11 -0.71,3.29 C-0.89,3.48 -1,3.74 -1,4 C-1,4 -1,5 -1,5c M-5.56 -8.31 C-3.91,-9.41 -1.98,-10 0,-10 C0,-10 0,-10 0,-10 C2.65,-10 5.2,-8.95 7.07,-7.07 C8.95,-5.2 10,-2.65 10,0 C10,1.98 9.41,3.91 8.32,5.56 C7.22,7.2 5.65,8.48 3.83,9.24 C2,10 -0.01,10.19 -1.95,9.81 C-3.89,9.42 -5.67,8.47 -7.07,7.07 C-8.47,5.67 -9.42,3.89 -9.81,1.95 C-10.19,0.01 -10,-2 -9.24,-3.83 C-8.48,-5.65 -7.2,-7.22 -5.56,-8.31c M3 1 C3,1 5,1 5,1 C5,1 5,-3 5,-3 C5,-3 3,-3 3,-3 C3,-3 3,1 3,1c M-0.02 4.03 C-0.02,4.03 0.03,4.03 0.03,4.03 C0.03,4.03 0.03,4 0.03,4 C0.03,3.99 0.02,3.99 0.02,3.98 C0.01,3.98 0.01,3.98 0,3.98 C-0.01,3.98 -0.01,3.98 -0.02,3.98 C-0.02,3.99 -0.02,3.99 -0.02,4 C-0.02,4 -0.02,4.03 -0.02,4.03c M-5 1 C-5,1 -3,1 -3,1 C-3,1 -3,-3 -3,-3 C-3,-3 -5,-3 -5,-3 C-5,-3 -5,1 -5,1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_pergola.xml b/packages/SystemUI/res/drawable/ic_device_pergola.xml new file mode 100644 index 000000000000..347ed3df6d55 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_pergola.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_pergola_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_pergola_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_refrigerator.xml b/packages/SystemUI/res/drawable/ic_device_refrigerator.xml new file mode 100644 index 000000000000..d9d73a3e30bd --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_refrigerator.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_refrigerator_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_refrigerator_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_remote_control.xml b/packages/SystemUI/res/drawable/ic_device_remote_control.xml new file mode 100644 index 000000000000..a950238899d2 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_remote_control.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_remote_control_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_remote_control_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_security_system.xml b/packages/SystemUI/res/drawable/ic_device_security_system.xml new file mode 100644 index 000000000000..a607c108ab5b --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_security_system.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_security_system_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_security_system_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_security_system_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_security_system_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_security_system_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_security_system_off_anim.xml new file mode 100644 index 000000000000..5d6c014c7b44 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_security_system_off_anim.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M3.54 -3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 4.96,-2.46 4.96,-2.46 C4.96,-2.46 3.54,-3.89 3.54,-3.89c "/> + </group> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M4.37 4.43 C5.44,2.86 6.01,1 6,-0.91 C6,-0.91 6,-5.61 6,-5.61 C6,-5.61 0,-7.86 0,-7.86 C0,-7.86 -6,-5.61 -6,-5.61 C-6,-5.61 -6,-0.91 -6,-0.91 C-6,1 -5.44,2.86 -4.36,4.43 C-3.29,6.01 -1.77,7.22 0,7.92 C1.77,7.22 3.3,6.01 4.37,4.43c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M-0.2 -11.3 C-6.22,-11.3 -11.1,-6.42 -11.1,-0.4 C-11.1,5.62 -6.22,10.5 -0.2,10.5 C5.82,10.5 10.7,5.62 10.7,-0.4 C10.7,-6.42 5.82,-11.3 -0.2,-11.3c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 3.54,-3.89 3.54,-3.89 C3.54,-3.89 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="0" android:valueFrom="M3.54 -3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 4.96,-2.46 4.96,-2.46 C4.96,-2.46 3.54,-3.89 3.54,-3.89c " android:valueTo="M-2.83 2.45 C-2.83,2.45 -1.42,1.06 -1.42,1.06 C-1.42,1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -2.83,2.45 -2.83,2.45c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="333" android:startOffset="167" android:valueFrom="M-2.83 2.45 C-2.83,2.45 -1.42,1.06 -1.42,1.06 C-1.42,1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -2.83,2.45 -2.83,2.45c " android:valueTo="M-4.95 0.35 C-4.95,0.35 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -4.95,0.35 -4.95,0.35c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M-0.2 -11.3 C-6.22,-11.3 -11.1,-6.42 -11.1,-0.4 C-11.1,5.62 -6.22,10.5 -0.2,10.5 C5.82,10.5 10.7,5.62 10.7,-0.4 C10.7,-6.42 5.82,-11.3 -0.2,-11.3c " android:valueTo="M-0.2 10.1 C-4.17,10.1 -7.4,13.33 -7.4,17.3 C-7.4,21.28 -4.17,24.5 -0.2,24.5 C3.78,24.5 7,21.28 7,17.3 C7,13.33 3.78,10.1 -0.2,10.1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="333" android:startOffset="0" android:valueFrom="M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 3.54,-3.89 3.54,-3.89 C3.54,-3.89 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueTo="M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 0,2.46 0,2.46 C0,2.46 -1.41,1.05 -1.41,1.05 C-1.41,1.05 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="333" android:valueFrom="M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 0,2.46 0,2.46 C0,2.46 -1.41,1.05 -1.41,1.05 C-1.41,1.05 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueTo="M-4.95 0.35 C-4.95,0.35 -4.95,0.35 -4.95,0.35 C-4.95,0.35 -3.54,-1.07 -3.54,-1.07 C-3.54,-1.07 -3.55,-1.09 -3.55,-1.09 C-3.55,-1.09 -3.55,-1.08 -3.55,-1.08 C-3.55,-1.08 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_security_system_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_security_system_on_anim.xml new file mode 100644 index 000000000000..445c6758dc41 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_security_system_on_anim.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4.95 0.35 C-4.95,0.35 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -4.95,0.35 -4.95,0.35c "/> + </group> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M4.37 4.43 C5.44,2.86 6.01,1 6,-0.91 C6,-0.91 6,-5.61 6,-5.61 C6,-5.61 0,-7.86 0,-7.86 C0,-7.86 -6,-5.61 -6,-5.61 C-6,-5.61 -6,-0.91 -6,-0.91 C-6,1 -5.44,2.86 -4.36,4.43 C-3.29,6.01 -1.77,7.22 0,7.92 C1.77,7.22 3.3,6.01 4.37,4.43c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M-0.2 10.1 C-4.17,10.1 -7.4,13.33 -7.4,17.3 C-7.4,21.28 -4.17,24.5 -0.2,24.5 C3.78,24.5 7,21.28 7,17.3 C7,13.33 3.78,10.1 -0.2,10.1c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4.95 0.35 C-4.95,0.35 -4.95,0.35 -4.95,0.35 C-4.95,0.35 -3.54,-1.07 -3.54,-1.07 C-3.54,-1.07 -3.55,-1.09 -3.55,-1.09 C-3.55,-1.09 -3.55,-1.08 -3.55,-1.08 C-3.55,-1.08 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="0" android:valueFrom="M-4.95 0.35 C-4.95,0.35 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -4.95,0.35 -4.95,0.35c " android:valueTo="M-2.83 2.45 C-2.83,2.45 -1.42,1.06 -1.42,1.06 C-1.42,1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -2.83,2.45 -2.83,2.45c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="233" android:startOffset="167" android:valueFrom="M-2.83 2.45 C-2.83,2.45 -1.42,1.06 -1.42,1.06 C-1.42,1.06 -1.41,1.06 -1.41,1.06 C-1.41,1.06 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 -1.41,3.89 -1.41,3.89 C-1.41,3.89 -2.83,2.45 -2.83,2.45c " android:valueTo="M3.54 -3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 3.54,-3.89 3.54,-3.89 C3.54,-3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 4.96,-2.46 4.96,-2.46 C4.96,-2.46 3.54,-3.89 3.54,-3.89c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M-0.2 10.1 C-4.17,10.1 -7.4,13.33 -7.4,17.3 C-7.4,21.28 -4.17,24.5 -0.2,24.5 C3.78,24.5 7,21.28 7,17.3 C7,13.33 3.78,10.1 -0.2,10.1c " android:valueTo="M-0.2 -11.3 C-6.22,-11.3 -11.1,-6.42 -11.1,-0.4 C-11.1,5.62 -6.22,10.5 -0.2,10.5 C5.82,10.5 10.7,5.62 10.7,-0.4 C10.7,-6.42 5.82,-11.3 -0.2,-11.3c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_G_0_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="0" android:valueFrom="M-4.95 0.35 C-4.95,0.35 -4.95,0.35 -4.95,0.35 C-4.95,0.35 -3.54,-1.07 -3.54,-1.07 C-3.54,-1.07 -3.55,-1.09 -3.55,-1.09 C-3.55,-1.09 -3.55,-1.08 -3.55,-1.08 C-3.55,-1.08 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueTo="M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 0,2.46 0,2.46 C0,2.46 -1.41,1.05 -1.41,1.05 C-1.41,1.05 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="333" android:startOffset="167" android:valueFrom="M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 0,2.46 0,2.46 C0,2.46 -1.41,1.05 -1.41,1.05 C-1.41,1.05 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueTo="M-4.95 0.35 C-4.95,0.35 -1.41,3.89 -1.41,3.89 C-1.41,3.89 4.95,-2.47 4.95,-2.47 C4.95,-2.47 3.54,-3.89 3.54,-3.89 C3.54,-3.89 -1.41,1.06 -1.41,1.06 C-1.41,1.06 -3.54,-1.06 -3.54,-1.06 C-3.54,-1.06 -4.95,0.35 -4.95,0.35c M-8 -7 C-8,-7 0,-10 0,-10 C0,-10 8,-7 8,-7 C8,-7 8,-0.91 8,-0.91 C8,4.14 4.59,8.85 0,10 C-4.59,8.85 -8,4.14 -8,-0.91 C-8,-0.91 -8,-7 -8,-7c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_set_top.xml b/packages/SystemUI/res/drawable/ic_device_set_top.xml new file mode 100644 index 000000000000..23a58c1b1a16 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_set_top.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_set_top_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_set_top_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_sprinkler.xml b/packages/SystemUI/res/drawable/ic_device_sprinkler.xml new file mode 100644 index 000000000000..e1a1e0460f35 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_sprinkler.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_sprinkler_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_sprinkler_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_styler.xml b/packages/SystemUI/res/drawable/ic_device_styler.xml new file mode 100644 index 000000000000..486290559091 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_styler.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_styler_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_styler_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_switch.xml b/packages/SystemUI/res/drawable/ic_device_switch.xml new file mode 100644 index 000000000000..554612d4b4b3 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_switch.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_switch_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_switch_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_switch_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_switch_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_switch_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_switch_off_anim.xml new file mode 100644 index 000000000000..ecfc5c1635df --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_switch_off_anim.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_7_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_7_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c "/> + </group> + <group android:name="_R_G_L_6_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_6_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-2 3 C-2,3 2,3 2,3 C2,3 2,-3 2,-3 C2,-3 -2,-3 -2,-3 C-2,-3 -2,3 -2,3c M-4 -5 C-4,-5 4,-5 4,-5 C4,-5 4,5 4,5 C4,5 -4,5 -4,5 C-4,5 -4,-5 -4,-5c "/> + </group> + <group android:name="_R_G_L_5_G" android:translateX="12" android:translateY="11" android:scaleY="0"> + <path android:name="_R_G_L_5_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -1 C-1,-1 1,-1 1,-1 C1,-1 1,1 1,1 C1,1 -1,1 -1,1 C-1,1 -1,-1 -1,-1c "/> + </group> + <group android:name="_R_G_L_4_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_4_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 0 C-1,0 1,0 1,0 C1,0 1,-2 1,-2 C1,-2 -1,-2 -1,-2 C-1,-2 -1,0 -1,0c M-2 -3 C-2,-3 2,-3 2,-3 C2,-3 2,3 2,3 C2,3 -2,3 -2,3 C-2,3 -2,-3 -2,-3c "/> + </group> + <group android:name="_R_G_L_3_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4 5 C-4,5 4,5 4,5 C4,5 4,-5 4,-5 C4,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c "/> + </group> + <group android:name="_R_G_L_2_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4 5 C-4,5 4.01,5 4.01,5 C4.01,5 4.01,-5 4.01,-5 C4.01,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c "/> + </group> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-2 3 C-2,3 2,3 2,3 C2,3 2,-3 2,-3 C2,-3 -2,-3 -2,-3 C-2,-3 -2,3 -2,3c M-4 -5 C-4,-5 4,-5 4,-5 C4,-5 4,5 4,5 C4,5 -4,5 -4,5 C-4,5 -4,-5 -4,-5c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="13" android:scaleY="0"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -1 C-1,-1 1,-1 1,-1 C1,-1 1,1 1,1 C1,1 -1,1 -1,1 C-1,1 -1,-1 -1,-1c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_4_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="350" android:startOffset="0" android:valueFrom="M-1 0 C-1,0 1,0 1,0 C1,0 1,-2 1,-2 C1,-2 -1,-2 -1,-2 C-1,-2 -1,0 -1,0c M-2 -3 C-2,-3 2,-3 2,-3 C2,-3 2,3 2,3 C2,3 -2,3 -2,3 C-2,3 -2,-3 -2,-3c " android:valueTo="M-1 2 C-1,2 1,2 1,2 C1,2 1,0 1,0 C1,0 -1,0 -1,0 C-1,0 -1,2 -1,2c M-2 -3 C-2,-3 2,-3 2,-3 C2,-3 2,3 2,3 C2,3 -2,3 -2,3 C-2,3 -2,-3 -2,-3c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.4,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_4_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="133" android:startOffset="0" android:valueFrom="M-4 5 C-4,5 4.01,5 4.01,5 C4.01,5 4.01,-5 4.01,-5 C4.01,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueTo="M-4 5 C-4,5 4.01,5 4.01,5 C4.01,5 4.01,-5 4.01,-5 C4.01,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.4,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="217" android:startOffset="133" android:valueFrom="M-4 5 C-4,5 4.01,5 4.01,5 C4.01,5 4.01,-5 4.01,-5 C4.01,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueTo="M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.4,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="317" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="317" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_switch_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_switch_on_anim.xml new file mode 100644 index 000000000000..bd2851970b4f --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_switch_on_anim.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_7_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_7_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c "/> + </group> + <group android:name="_R_G_L_6_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_6_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-2 3 C-2,3 2,3 2,3 C2,3 2,-3 2,-3 C2,-3 -2,-3 -2,-3 C-2,-3 -2,3 -2,3c M-4 -5 C-4,-5 4,-5 4,-5 C4,-5 4,5 4,5 C4,5 -4,5 -4,5 C-4,5 -4,-5 -4,-5c "/> + </group> + <group android:name="_R_G_L_5_G" android:translateX="12" android:translateY="11" android:scaleY="0"> + <path android:name="_R_G_L_5_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -1 C-1,-1 1,-1 1,-1 C1,-1 1,1 1,1 C1,1 -1,1 -1,1 C-1,1 -1,-1 -1,-1c "/> + </group> + <group android:name="_R_G_L_4_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_4_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 0 C-1,0 1,0 1,0 C1,0 1,-2 1,-2 C1,-2 -1,-2 -1,-2 C-1,-2 -1,0 -1,0c M-2 -3 C-2,-3 2,-3 2,-3 C2,-3 2,3 2,3 C2,3 -2,3 -2,3 C-2,3 -2,-3 -2,-3c "/> + </group> + <group android:name="_R_G_L_3_G" android:translateX="12" android:translateY="12" android:scaleY="0"> + <path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4 5 C-4,5 4,5 4,5 C4,5 4,-5 4,-5 C4,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c "/> + </group> + <group android:name="_R_G_L_2_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c "/> + </group> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-2 3 C-2,3 2,3 2,3 C2,3 2,-3 2,-3 C2,-3 -2,-3 -2,-3 C-2,-3 -2,3 -2,3c M-4 -5 C-4,-5 4,-5 4,-5 C4,-5 4,5 4,5 C4,5 -4,5 -4,5 C-4,5 -4,-5 -4,-5c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="13"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1 -1 C-1,-1 1,-1 1,-1 C1,-1 1,1 1,1 C1,1 -1,1 -1,1 C-1,1 -1,-1 -1,-1c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_4_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="300" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="133" android:startOffset="0" android:valueFrom="M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueTo="M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.4,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="217" android:startOffset="133" android:valueFrom="M-7 7 C-7,7 7,7 7,7 C7,7 7,-7 7,-7 C7,-7 -7,-7 -7,-7 C-7,-7 -7,7 -7,7c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueTo="M-4 5 C-4,5 4.01,5 4.01,5 C4.01,5 4.01,-5 4.01,-5 C4.01,-5 -4,-5 -4,-5 C-4,-5 -4,5 -4,5c M-7 -9 C-7,-9 7,-9 7,-9 C7.53,-9 8.04,-8.79 8.41,-8.41 C8.79,-8.04 9,-7.53 9,-7 C9,-7 9,7 9,7 C9,7.53 8.79,8.04 8.41,8.41 C8.04,8.79 7.53,9 7,9 C7,9 -7,9 -7,9 C-7.53,9 -8.04,8.79 -8.41,8.41 C-8.79,8.04 -9,7.53 -9,7 C-9,7 -9,-7 -9,-7 C-9,-7.53 -8.79,-8.04 -8.41,-8.41 C-8.04,-8.79 -7.53,-9 -7,-9c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.4,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateXY" android:duration="350" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,13C 12,12.667 12,11.333 12,11"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.4,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat.xml b/packages/SystemUI/res/drawable/ic_device_thermostat.xml new file mode 100644 index 000000000000..f73387dcbbd7 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_thermostat.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_thermostat_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_thermostat_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_thermostat_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_thermostat_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_off_anim.xml new file mode 100644 index 000000000000..28ac6150ee63 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_thermostat_off_anim.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="11.9" android:scaleX="1.05" android:scaleY="1.05"> + <group android:name="_R_G_L_1_C_0_G"> + <clip-path android:name="_R_G_L_1_C_0" android:pathData=" M5.32 -2.1 C5.32,-2.1 -4.85,-2.1 -4.85,-2.1 C-4.85,-2.1 -4.85,7.57 -4.85,7.57 C-4.85,7.57 5.32,7.57 5.32,7.57 C5.32,7.57 5.32,-2.1 5.32,-2.1c "/> + <group android:name="_R_G_L_1_C_0_G_G"> + <path android:name="_R_G_L_1_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M2.37 5.82 C2.37,5.82 2.4,5.77 2.4,5.77 C2.4,5.77 2.4,5.77 2.4,5.77 C2.79,5.26 3,4.64 3,4 C3,3.54 2.89,3.08 2.68,2.66 C2.47,2.24 2.17,1.88 1.8,1.6 C1.8,1.6 1,1 1,1 C1,1 1,-6 1,-6 C1,-6.26 0.9,-6.52 0.71,-6.71 C0.52,-6.89 0.27,-7 0,-7 C-0.26,-7 -0.52,-6.89 -0.71,-6.71 C-0.89,-6.52 -1,-6.26 -1,-6 C-1,-6 -1,1 -1,1 C-1,1 -1.8,1.6 -1.8,1.6 C-2.17,1.88 -2.47,2.24 -2.68,2.66 C-2.89,3.08 -3,3.54 -3,4 C-3,4.64 -2.78,5.27 -2.4,5.78 C-2.4,5.78 -2.32,5.88 -2.32,5.88 C-2.04,6.23 -1.68,6.52 -1.27,6.71 C-0.86,6.91 -0.41,7.01 0.04,7 C0.49,6.99 0.94,6.89 1.34,6.68 C1.75,6.48 2.09,6.18 2.37,5.82c "/> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M2.37 5.82 C2.37,5.82 2.4,5.77 2.4,5.77 C2.4,5.77 2.4,5.77 2.4,5.77 C2.79,5.26 3,4.64 3,4 C3,3.54 2.89,3.08 2.68,2.66 C2.47,2.24 2.17,1.88 1.8,1.6 C1.8,1.6 1,1 1,1 C1,1 1,-6 1,-6 C1,-6.26 0.9,-6.52 0.71,-6.71 C0.52,-6.89 0.27,-7 0,-7 C-0.26,-7 -0.52,-6.89 -0.71,-6.71 C-0.89,-6.52 -1,-6.26 -1,-6 C-1,-6 -1,1 -1,1 C-1,1 -1.8,1.6 -1.8,1.6 C-2.17,1.88 -2.47,2.24 -2.68,2.66 C-2.89,3.08 -3,3.54 -3,4 C-3,4.64 -2.78,5.27 -2.4,5.78 C-2.4,5.78 -2.32,5.88 -2.32,5.88 C-2.04,6.23 -1.68,6.52 -1.27,6.71 C-0.86,6.91 -0.41,7.01 0.04,7 C0.49,6.99 0.94,6.89 1.34,6.68 C1.75,6.48 2.09,6.18 2.37,5.82c M3 -6 C3,-6 3,0 3,0 C3.62,0.47 4.12,1.07 4.47,1.76 C4.82,2.46 5,3.22 5,4 C5,5.07 4.65,6.12 4,6.97 C4,6.97 4,7 4,7 C4,7 3.98,7 3.98,7 C3.52,7.62 2.92,8.13 2.23,8.47 C1.54,8.82 0.77,9 0,9 C-0.77,9 -1.54,8.82 -2.23,8.47 C-2.92,8.13 -3.52,7.62 -3.98,7 C-3.98,7 -4,7 -4,7 C-4,7 -4,6.97 -4,6.97 C-4.65,6.12 -5,5.07 -5,4 C-5,3.22 -4.82,2.46 -4.47,1.76 C-4.12,1.07 -3.62,0.47 -3,0 C-3,0 -3,-6 -3,-6 C-3,-6.8 -2.68,-7.56 -2.12,-8.12 C-1.56,-8.68 -0.8,-9 0,-9 C0.8,-9 1.56,-8.68 2.12,-8.12 C2.68,-7.56 3,-6.8 3,-6c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M5.32 -2.1 C5.32,-2.1 -4.85,-2.1 -4.85,-2.1 C-4.85,-2.1 -4.85,7.57 -4.85,7.57 C-4.85,7.57 5.32,7.57 5.32,7.57 C5.32,7.57 5.32,-2.1 5.32,-2.1c " android:valueTo="M5.32 7.6 C5.32,7.6 -4.85,7.6 -4.85,7.6 C-4.85,7.6 -4.85,7.57 -4.85,7.57 C-4.85,7.57 5.32,7.57 5.32,7.57 C5.32,7.57 5.32,7.6 5.32,7.6c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_on_anim.xml new file mode 100644 index 000000000000..36acf3359aa8 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_thermostat_on_anim.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="11.9" android:scaleX="1.05" android:scaleY="1.05"> + <group android:name="_R_G_L_1_C_0_G"> + <clip-path android:name="_R_G_L_1_C_0" android:pathData=" M5.32 7.6 C5.32,7.6 -4.85,7.6 -4.85,7.6 C-4.85,7.6 -4.85,7.57 -4.85,7.57 C-4.85,7.57 5.32,7.57 5.32,7.57 C5.32,7.57 5.32,7.6 5.32,7.6c "/> + <group android:name="_R_G_L_1_C_0_G_G"> + <path android:name="_R_G_L_1_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M2.37 5.82 C2.37,5.82 2.4,5.77 2.4,5.77 C2.4,5.77 2.4,5.77 2.4,5.77 C2.79,5.26 3,4.64 3,4 C3,3.54 2.89,3.08 2.68,2.66 C2.47,2.24 2.17,1.88 1.8,1.6 C1.8,1.6 1,1 1,1 C1,1 1,-6 1,-6 C1,-6.26 0.9,-6.52 0.71,-6.71 C0.52,-6.89 0.27,-7 0,-7 C-0.26,-7 -0.52,-6.89 -0.71,-6.71 C-0.89,-6.52 -1,-6.26 -1,-6 C-1,-6 -1,1 -1,1 C-1,1 -1.8,1.6 -1.8,1.6 C-2.17,1.88 -2.47,2.24 -2.68,2.66 C-2.89,3.08 -3,3.54 -3,4 C-3,4.64 -2.78,5.27 -2.4,5.78 C-2.4,5.78 -2.32,5.88 -2.32,5.88 C-2.04,6.23 -1.68,6.52 -1.27,6.71 C-0.86,6.91 -0.41,7.01 0.04,7 C0.49,6.99 0.94,6.89 1.34,6.68 C1.75,6.48 2.09,6.18 2.37,5.82c "/> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M2.37 5.82 C2.37,5.82 2.4,5.77 2.4,5.77 C2.4,5.77 2.4,5.77 2.4,5.77 C2.79,5.26 3,4.64 3,4 C3,3.54 2.89,3.08 2.68,2.66 C2.47,2.24 2.17,1.88 1.8,1.6 C1.8,1.6 1,1 1,1 C1,1 1,-6 1,-6 C1,-6.26 0.9,-6.52 0.71,-6.71 C0.52,-6.89 0.27,-7 0,-7 C-0.26,-7 -0.52,-6.89 -0.71,-6.71 C-0.89,-6.52 -1,-6.26 -1,-6 C-1,-6 -1,1 -1,1 C-1,1 -1.8,1.6 -1.8,1.6 C-2.17,1.88 -2.47,2.24 -2.68,2.66 C-2.89,3.08 -3,3.54 -3,4 C-3,4.64 -2.78,5.27 -2.4,5.78 C-2.4,5.78 -2.32,5.88 -2.32,5.88 C-2.04,6.23 -1.68,6.52 -1.27,6.71 C-0.86,6.91 -0.41,7.01 0.04,7 C0.49,6.99 0.94,6.89 1.34,6.68 C1.75,6.48 2.09,6.18 2.37,5.82c M3 -6 C3,-6 3,0 3,0 C3.62,0.47 4.12,1.07 4.47,1.76 C4.82,2.46 5,3.22 5,4 C5,5.07 4.65,6.12 4,6.97 C4,6.97 4,7 4,7 C4,7 3.98,7 3.98,7 C3.52,7.62 2.92,8.13 2.23,8.47 C1.54,8.82 0.77,9 0,9 C-0.77,9 -1.54,8.82 -2.23,8.47 C-2.92,8.13 -3.52,7.62 -3.98,7 C-3.98,7 -4,7 -4,7 C-4,7 -4,6.97 -4,6.97 C-4.65,6.12 -5,5.07 -5,4 C-5,3.22 -4.82,2.46 -4.47,1.76 C-4.12,1.07 -3.62,0.47 -3,0 C-3,0 -3,-6 -3,-6 C-3,-6.8 -2.68,-7.56 -2.12,-8.12 C-1.56,-8.68 -0.8,-9 0,-9 C0.8,-9 1.56,-8.68 2.12,-8.12 C2.68,-7.56 3,-6.8 3,-6c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M5.32 7.6 C5.32,7.6 -4.85,7.6 -4.85,7.6 C-4.85,7.6 -4.85,7.57 -4.85,7.57 C-4.85,7.57 5.32,7.57 5.32,7.57 C5.32,7.57 5.32,7.6 5.32,7.6c " android:valueTo="M5.32 -2.1 C5.32,-2.1 -4.85,-2.1 -4.85,-2.1 C-4.85,-2.1 -4.85,7.57 -4.85,7.57 C-4.85,7.57 5.32,7.57 5.32,7.57 C5.32,7.57 5.32,-2.1 5.32,-2.1c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_tv.xml b/packages/SystemUI/res/drawable/ic_device_tv.xml new file mode 100644 index 000000000000..4baf8a11b5eb --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_tv.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_tv_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_tv_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_tv_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_tv_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_tv_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_tv_off_anim.xml new file mode 100644 index 000000000000..0f5a5f5fd199 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_tv_off_anim.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="12.5"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-8 4.5 C-8,4.5 8,4.5 8,4.5 C8,4.5 8,-6.5 8,-6.5 C8,-6.5 -8,-6.5 -8,-6.5 C-8,-6.5 -8,4.5 -8,4.5c M-8 -8.5 C-8,-8.5 8,-8.5 8,-8.5 C8,-8.5 8,-8.5 8,-8.5 C8.53,-8.5 9.04,-8.29 9.41,-7.91 C9.79,-7.54 10,-7.03 10,-6.5 C10,-6.5 10,4.5 10,4.5 C10,5.03 9.79,5.54 9.41,5.91 C9.04,6.29 8.53,6.5 8,6.5 C8,6.5 8,8.5 8,8.5 C8,8.5 7,8.5 7,8.5 C7,8.5 6.33,6.5 6.33,6.5 C6.33,6.5 -6.33,6.5 -6.33,6.5 C-6.33,6.5 -7,8.5 -7,8.5 C-7,8.5 -8,8.5 -8,8.5 C-8,8.5 -8,6.5 -8,6.5 C-8.53,6.5 -9.04,6.29 -9.41,5.91 C-9.79,5.54 -10,5.03 -10,4.5 C-10,4.5 -10,-6.5 -10,-6.5 C-10,-7.03 -9.79,-7.54 -9.41,-7.91 C-9.04,-8.29 -8.53,-8.5 -8,-8.5c "/> + </group> + <group android:name="_R_G_L_0_G"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M11.94 32.38 C11.74,11.73 -9.06,11.38 -9.06,11.38 C-9.06,11.38 11.64,11.11 11.94,-9.62 C11.85,11.21 32.94,11.38 32.94,11.38 C32.94,11.38 11.74,11.52 11.94,32.38c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M5 7 C5,7 19,7 19,7 C19,7 19,16 19,16 C19,16 5,16 5,16 C5,16 5,7 5,7c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M11.94 32.38 C11.74,11.73 -9.06,11.38 -9.06,11.38 C-9.06,11.38 11.64,11.11 11.94,-9.62 C11.85,11.21 32.94,11.38 32.94,11.38 C32.94,11.38 11.74,11.52 11.94,32.38c " android:valueTo="M11.94 11.56 C11.94,11.38 11.75,11.38 11.75,11.38 C11.75,11.38 11.94,11.37 11.94,11.19 C11.94,11.37 12.13,11.38 12.13,11.38 C12.13,11.38 11.94,11.38 11.94,11.56c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_tv_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_tv_on_anim.xml new file mode 100644 index 000000000000..0bd7cf2c526e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_tv_on_anim.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G"> + <group android:name="_R_G_L_1_C_0_G"> + <clip-path android:name="_R_G_L_1_C_0" android:pathData=" M11.94 11.56 C11.94,11.38 11.75,11.38 11.75,11.38 C11.75,11.38 11.94,11.37 11.94,11.19 C11.94,11.37 12.13,11.38 12.13,11.38 C12.13,11.38 11.94,11.38 11.94,11.56c "/> + <group android:name="_R_G_L_1_C_0_G_G"> + <path android:name="_R_G_L_1_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M5 7 C5,7 19,7 19,7 C19,7 19,16 19,16 C19,16 5,16 5,16 C5,16 5,7 5,7c "/> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12.5"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-8 4.5 C-8,4.5 8,4.5 8,4.5 C8,4.5 8,-6.5 8,-6.5 C8,-6.5 -8,-6.5 -8,-6.5 C-8,-6.5 -8,4.5 -8,4.5c M-8 -8.5 C-8,-8.5 8,-8.5 8,-8.5 C8,-8.5 8,-8.5 8,-8.5 C8.53,-8.5 9.04,-8.29 9.41,-7.91 C9.79,-7.54 10,-7.03 10,-6.5 C10,-6.5 10,4.5 10,4.5 C10,5.03 9.79,5.54 9.41,5.91 C9.04,6.29 8.53,6.5 8,6.5 C8,6.5 8,8.5 8,8.5 C8,8.5 7,8.5 7,8.5 C7,8.5 6.33,6.5 6.33,6.5 C6.33,6.5 -6.33,6.5 -6.33,6.5 C-6.33,6.5 -7,8.5 -7,8.5 C-7,8.5 -8,8.5 -8,8.5 C-8,8.5 -8,6.5 -8,6.5 C-8.53,6.5 -9.04,6.29 -9.41,5.91 C-9.79,5.54 -10,5.03 -10,4.5 C-10,4.5 -10,-6.5 -10,-6.5 C-10,-7.03 -9.79,-7.54 -9.41,-7.91 C-9.04,-8.29 -8.53,-8.5 -8,-8.5c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M11.94 11.56 C11.94,11.38 11.75,11.38 11.75,11.38 C11.75,11.38 11.94,11.37 11.94,11.19 C11.94,11.37 12.13,11.38 12.13,11.38 C12.13,11.38 11.94,11.38 11.94,11.56c " android:valueTo="M11.94 32.38 C11.74,11.73 -9.06,11.38 -9.06,11.38 C-9.06,11.38 11.64,11.11 11.94,-9.62 C11.85,11.21 32.94,11.38 32.94,11.38 C32.94,11.38 11.74,11.52 11.94,32.38c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_unknown.xml b/packages/SystemUI/res/drawable/ic_device_unknown.xml new file mode 100644 index 000000000000..b8bfe242277e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_unknown.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_unknown_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_unknown_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum.xml b/packages/SystemUI/res/drawable/ic_device_vacuum.xml new file mode 100644 index 000000000000..cbe42b9d12aa --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_vacuum.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_vacuum_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_vacuum_on" /> + <transition + android:fromId="@id/off" + android:toId="@id/on" + android:drawable="@drawable/ic_device_vacuum_on_anim" /> + <transition + android:fromId="@id/on" + android:toId="@id/off" + android:drawable="@drawable/ic_device_vacuum_off_anim" /> +</animated-selector> diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum_off_anim.xml b/packages/SystemUI/res/drawable/ic_device_vacuum_off_anim.xml new file mode 100644 index 000000000000..7e2d1df3357a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_vacuum_off_anim.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="11.5"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M11 10.5 C11,10.5 11,8.5 11,8.5 C11,8.5 8.66,8.5 8.66,8.5 C8.66,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 6.49,8.5 6.49,8.5 C6.49,8.5 4,8.5 4,8.5 C4,8.5 4,10.5 4,10.5 C4,10.5 11,10.5 11,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12.5" android:translateY="11.5"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M2.15 -2.94 C2.15,-2.94 -12,-2.94 -12,-2.94 C-12,-2.94 -12,10.58 -12,10.58 C-12,10.58 2.15,10.58 2.15,10.58 C2.15,10.58 2.15,-2.94 2.15,-2.94c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-5.5 -2.5 C-5.5,-2.5 -3.5,-2.5 -3.5,-2.5 C-2.44,-2.5 -1.42,-2.08 -0.67,-1.33 C0.08,-0.58 0.5,0.44 0.5,1.5 C0.5,1.5 0.5,10.5 0.5,10.5 C0.5,10.5 -4.52,10.5 -4.52,10.5 C-3.86,9.64 -3.5,8.59 -3.5,7.5 C-3.5,6.67 -3.7,5.85 -4.1,5.12 C-4.49,4.39 -5.06,3.77 -5.76,3.31 C-6.45,2.86 -7.25,2.59 -8.08,2.52 C-8.91,2.45 -9.74,2.59 -10.5,2.93 C-10.5,2.93 -10.5,-2.5 -10.5,-2.5 C-10.5,-2.5 -7.5,-2.5 -7.5,-2.5 C-7.5,-2.5 -5.5,-2.5 -5.5,-2.5c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="83" android:startOffset="0" android:valueFrom="M11 10.5 C11,10.5 11,8.5 11,8.5 C11,8.5 8.66,8.5 8.66,8.5 C8.66,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 6.49,8.5 6.49,8.5 C6.49,8.5 4,8.5 4,8.5 C4,8.5 4,10.5 4,10.5 C4,10.5 11,10.5 11,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueTo="M6.47 10.5 C6.47,10.5 6.47,8.5 6.47,8.5 C6.47,8.5 4.13,8.5 4.13,8.5 C4.13,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 1.96,8.5 1.96,8.5 C1.96,8.5 -0.53,8.5 -0.53,8.5 C-0.53,8.5 -0.53,10.5 -0.53,10.5 C-0.53,10.5 6.47,10.5 6.47,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="417" android:startOffset="83" android:valueFrom="M6.47 10.5 C6.47,10.5 6.47,8.5 6.47,8.5 C6.47,8.5 4.13,8.5 4.13,8.5 C4.13,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 1.96,8.5 1.96,8.5 C1.96,8.5 -0.53,8.5 -0.53,8.5 C-0.53,8.5 -0.53,10.5 -0.53,10.5 C-0.53,10.5 6.47,10.5 6.47,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueTo="M11 10.5 C11,10.5 11,8.5 11,8.5 C11,8.5 8.66,8.5 8.66,8.5 C8.66,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 6.49,8.5 6.49,8.5 C6.49,8.5 4,8.5 4,8.5 C4,8.5 4,10.5 4,10.5 C4,10.5 11,10.5 11,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M2.15 -2.94 C2.15,-2.94 -12,-2.94 -12,-2.94 C-12,-2.94 -12,10.58 -12,10.58 C-12,10.58 2.15,10.58 2.15,10.58 C2.15,10.58 2.15,-2.94 2.15,-2.94c " android:valueTo="M2.15 11.63 C2.15,11.63 -12,11.63 -12,11.63 C-12,11.63 -12,10.58 -12,10.58 C-12,10.58 2.15,10.58 2.15,10.58 C2.15,10.58 2.15,11.63 2.15,11.63c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum_on_anim.xml b/packages/SystemUI/res/drawable/ic_device_vacuum_on_anim.xml new file mode 100644 index 000000000000..3c101d3c123a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_vacuum_on_anim.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G" android:translateX="12" android:translateY="11.5"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M11 10.5 C11,10.5 11,8.5 11,8.5 C11,8.5 8.66,8.5 8.66,8.5 C8.66,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 6.49,8.5 6.49,8.5 C6.49,8.5 4,8.5 4,8.5 C4,8.5 4,10.5 4,10.5 C4,10.5 11,10.5 11,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c "/> + </group> + <group android:name="_R_G_L_0_G" android:translateX="12.5" android:translateY="11.5"> + <group android:name="_R_G_L_0_C_0_G"> + <clip-path android:name="_R_G_L_0_C_0" android:pathData=" M2.15 11.63 C2.15,11.63 -12,11.63 -12,11.63 C-12,11.63 -12,10.58 -12,10.58 C-12,10.58 2.15,10.58 2.15,10.58 C2.15,10.58 2.15,11.63 2.15,11.63c "/> + <group android:name="_R_G_L_0_C_0_G_G"> + <path android:name="_R_G_L_0_G_G_0_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-5.5 -2.5 C-5.5,-2.5 -3.5,-2.5 -3.5,-2.5 C-2.44,-2.5 -1.42,-2.08 -0.67,-1.33 C0.08,-0.58 0.5,0.44 0.5,1.5 C0.5,1.5 0.5,10.5 0.5,10.5 C0.5,10.5 -4.52,10.5 -4.52,10.5 C-3.86,9.64 -3.5,8.59 -3.5,7.5 C-3.5,6.67 -3.7,5.85 -4.1,5.12 C-4.49,4.39 -5.06,3.77 -5.76,3.31 C-6.45,2.86 -7.25,2.59 -8.08,2.52 C-8.91,2.45 -9.74,2.59 -10.5,2.93 C-10.5,2.93 -10.5,-2.5 -10.5,-2.5 C-10.5,-2.5 -7.5,-2.5 -7.5,-2.5 C-7.5,-2.5 -5.5,-2.5 -5.5,-2.5c "/> + </group> + </group> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="83" android:startOffset="0" android:valueFrom="M11 10.5 C11,10.5 11,8.5 11,8.5 C11,8.5 8.66,8.5 8.66,8.5 C8.66,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 6.49,8.5 6.49,8.5 C6.49,8.5 4,8.5 4,8.5 C4,8.5 4,10.5 4,10.5 C4,10.5 11,10.5 11,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueTo="M6.47 10.5 C6.47,10.5 6.47,8.5 6.47,8.5 C6.47,8.5 4.13,8.5 4.13,8.5 C4.13,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 1.96,8.5 1.96,8.5 C1.96,8.5 -0.53,8.5 -0.53,8.5 C-0.53,8.5 -0.53,10.5 -0.53,10.5 C-0.53,10.5 6.47,10.5 6.47,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="417" android:startOffset="83" android:valueFrom="M6.47 10.5 C6.47,10.5 6.47,8.5 6.47,8.5 C6.47,8.5 4.13,8.5 4.13,8.5 C4.13,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 1.96,8.5 1.96,8.5 C1.96,8.5 -0.53,8.5 -0.53,8.5 C-0.53,8.5 -0.53,10.5 -0.53,10.5 C-0.53,10.5 6.47,10.5 6.47,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueTo="M11 10.5 C11,10.5 11,8.5 11,8.5 C11,8.5 8.66,8.5 8.66,8.5 C8.66,8.5 1.86,-7.68 1.86,-7.68 C1.45,-8.66 0.71,-9.47 -0.23,-9.97 C-1.17,-10.46 -2.26,-10.62 -3.3,-10.41 C-4.34,-10.2 -5.28,-9.63 -5.96,-8.81 C-6.63,-7.98 -7,-6.95 -7,-5.89 C-7,-5.89 -7,-2.5 -7,-2.5 C-7,-2.5 -10,-2.5 -10,-2.5 C-10,-2.5 -10,2.92 -10,2.92 C-9.37,2.64 -8.69,2.5 -8,2.5 C-8,2.5 -8,-0.5 -8,-0.5 C-8,-0.5 -3,-0.5 -3,-0.5 C-2.47,-0.5 -1.96,-0.29 -1.59,0.09 C-1.21,0.46 -1,0.97 -1,1.5 C-1,1.5 -1,8.5 -1,8.5 C-1,8.5 -3.1,8.5 -3.1,8.5 C-3.25,9.23 -3.56,9.91 -4.01,10.5 C-4.01,10.5 1,10.5 1,10.5 C1,10.5 1,1.5 1,1.5 C1,0.44 0.58,-0.58 -0.17,-1.33 C-0.92,-2.08 -1.94,-2.5 -3,-2.5 C-3,-2.5 -5,-2.5 -5,-2.5 C-5,-2.5 -5,-5.89 -5,-5.89 C-5,-6.49 -4.79,-7.07 -4.41,-7.54 C-4.03,-8.01 -3.5,-8.33 -2.91,-8.45 C-2.32,-8.57 -1.71,-8.48 -1.18,-8.2 C-0.64,-7.92 -0.22,-7.46 0.01,-6.91 C0.01,-6.91 6.49,8.5 6.49,8.5 C6.49,8.5 4,8.5 4,8.5 C4,8.5 4,10.5 4,10.5 C4,10.5 11,10.5 11,10.5c M-8.56 8.33 C-8.39,8.44 -8.2,8.5 -8,8.5 C-7.73,8.5 -7.48,8.4 -7.29,8.21 C-7.1,8.02 -7,7.77 -7,7.5 C-7,7.3 -7.06,7.11 -7.17,6.94 C-7.28,6.78 -7.43,6.65 -7.62,6.58 C-7.8,6.5 -8,6.48 -8.19,6.52 C-8.39,6.56 -8.57,6.65 -8.71,6.79 C-8.85,6.93 -8.94,7.11 -8.98,7.31 C-9.02,7.5 -9,7.7 -8.92,7.88 C-8.85,8.07 -8.72,8.22 -8.56,8.33c M-9.67 5.01 C-9.17,4.68 -8.59,4.5 -8,4.5 C-8,4.5 -8,4.5 -8,4.5 C-7.2,4.5 -6.44,4.82 -5.88,5.38 C-5.32,5.94 -5,6.7 -5,7.5 C-5,8.09 -5.18,8.67 -5.51,9.17 C-5.84,9.66 -6.3,10.05 -6.85,10.27 C-7.4,10.5 -8,10.56 -8.59,10.44 C-9.17,10.33 -9.7,10.04 -10.12,9.62 C-10.54,9.2 -10.83,8.67 -10.94,8.09 C-11.06,7.5 -11,6.9 -10.77,6.35 C-10.54,5.8 -10.16,5.34 -9.67,5.01c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_C_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="500" android:startOffset="0" android:valueFrom="M2.15 11.63 C2.15,11.63 -12,11.63 -12,11.63 C-12,11.63 -12,10.58 -12,10.58 C-12,10.58 2.15,10.58 2.15,10.58 C2.15,10.58 2.15,11.63 2.15,11.63c " android:valueTo="M2.15 -2.94 C2.15,-2.94 -12,-2.94 -12,-2.94 C-12,-2.94 -12,10.58 -12,10.58 C-12,10.58 2.15,10.58 2.15,10.58 C2.15,10.58 2.15,-2.94 2.15,-2.94c " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="750" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_device_valve.xml b/packages/SystemUI/res/drawable/ic_device_valve.xml new file mode 100644 index 000000000000..ce8342a153dd --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_valve.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_valve_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_valve_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_washer.xml b/packages/SystemUI/res/drawable/ic_device_washer.xml new file mode 100644 index 000000000000..5cc82d9cb1f9 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_washer.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_washer_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_washer_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_water.xml b/packages/SystemUI/res/drawable/ic_device_water.xml new file mode 100644 index 000000000000..2ec76dffc2f4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_water.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_water_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_water_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_water_heater.xml b/packages/SystemUI/res/drawable/ic_device_water_heater.xml new file mode 100644 index 000000000000..71eddf9eaca3 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_water_heater.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_water_heater_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_water_heater_on" /> +</selector> diff --git a/packages/SystemUI/res/drawable/ic_device_window.xml b/packages/SystemUI/res/drawable/ic_device_window.xml new file mode 100644 index 000000000000..4ec61c1bb372 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_device_window.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/off" + android:state_enabled="false" + android:drawable="@drawable/ic_device_window_off" /> + <item + android:id="@+id/on" + android:state_enabled="true" + android:drawable="@drawable/ic_device_window_on" /> +</selector> diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml index d469e0f187e0..fce4610b934b 100644 --- a/packages/SystemUI/res/layout/global_screenshot.xml +++ b/packages/SystemUI/res/layout/global_screenshot.xml @@ -14,9 +14,8 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<androidx.constraintlayout.widget.ConstraintLayout +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/global_screenshot_frame" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -24,72 +23,18 @@ android:id="@+id/global_screenshot_actions_background" android:layout_height="@dimen/screenshot_bg_protection_height" android:layout_width="match_parent" + android:layout_gravity="bottom" android:alpha="0.0" - android:src="@drawable/screenshot_actions_background_protection" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent"/> - <ImageView - android:id="@+id/global_screenshot_actions_container_background" - android:visibility="gone" - android:layout_height="0dp" - android:layout_width="0dp" - android:elevation="1dp" - android:background="@drawable/action_chip_container_background" - android:layout_marginStart="@dimen/screenshot_action_container_margin_horizontal" - app:layout_constraintBottom_toBottomOf="@+id/global_screenshot_actions_container" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/global_screenshot_actions_container" - app:layout_constraintEnd_toEndOf="@+id/global_screenshot_actions_container"/> - <HorizontalScrollView - android:id="@+id/global_screenshot_actions_container" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/screenshot_action_container_margin_horizontal" - android:layout_marginBottom="@dimen/screenshot_action_container_offset_y" - android:paddingHorizontal="@dimen/screenshot_action_container_padding_right" - android:paddingVertical="@dimen/screenshot_action_container_padding_vertical" - android:elevation="1dp" - android:scrollbars="none" - app:layout_constraintHorizontal_bias="0" - app:layout_constraintWidth_percent="1.0" - app:layout_constraintWidth_max="wrap" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@+id/global_screenshot_preview" - app:layout_constraintEnd_toEndOf="parent"> - <LinearLayout - android:id="@+id/global_screenshot_actions" - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> - </HorizontalScrollView> + android:src="@drawable/screenshot_actions_background_protection"/> <ImageView android:id="@+id/global_screenshot_animated_view" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="center" android:visibility="gone" android:elevation="@dimen/screenshot_preview_elevation" android:background="@drawable/screenshot_rounded_corners" android:adjustViewBounds="true"/> - <include layout="@layout/global_screenshot_preview"/> - <FrameLayout - android:id="@+id/global_screenshot_dismiss_button" - android:layout_width="@dimen/screenshot_dismiss_button_tappable_size" - android:layout_height="@dimen/screenshot_dismiss_button_tappable_size" - android:elevation="7dp" - android:visibility="gone" - android:contentDescription="@string/screenshot_dismiss_ui_description" - app:layout_constraintStart_toEndOf="@+id/global_screenshot_preview" - app:layout_constraintEnd_toEndOf="@+id/global_screenshot_preview" - app:layout_constraintTop_toTopOf="@+id/global_screenshot_preview" - app:layout_constraintBottom_toTopOf="@+id/global_screenshot_preview"> - <ImageView - android:id="@+id/global_screenshot_dismiss_image" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_margin="@dimen/screenshot_dismiss_button_margin" - android:src="@drawable/screenshot_cancel"/> - </FrameLayout> <ImageView android:id="@+id/global_screenshot_flash" android:layout_width="match_parent" @@ -103,4 +48,5 @@ android:layout_height="match_parent" android:visibility="gone" android:pointerIcon="crosshair"/> -</androidx.constraintlayout.widget.ConstraintLayout> + <include layout="@layout/global_screenshot_static"/> +</FrameLayout> diff --git a/packages/SystemUI/res/layout/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml new file mode 100644 index 000000000000..a46823d9bc38 --- /dev/null +++ b/packages/SystemUI/res/layout/global_screenshot_static.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:fitsSystemWindows="true" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <ImageView + android:id="@+id/global_screenshot_actions_container_background" + android:visibility="gone" + android:layout_height="0dp" + android:layout_width="0dp" + android:elevation="1dp" + android:background="@drawable/action_chip_container_background" + android:layout_marginStart="@dimen/screenshot_action_container_margin_horizontal" + app:layout_constraintBottom_toBottomOf="@+id/global_screenshot_actions_container" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@+id/global_screenshot_actions_container" + app:layout_constraintEnd_toEndOf="@+id/global_screenshot_actions_container"/> + <HorizontalScrollView + android:id="@+id/global_screenshot_actions_container" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/screenshot_action_container_margin_horizontal" + android:layout_marginBottom="@dimen/screenshot_action_container_offset_y" + android:paddingHorizontal="@dimen/screenshot_action_container_padding_right" + android:paddingVertical="@dimen/screenshot_action_container_padding_vertical" + android:elevation="1dp" + android:scrollbars="none" + app:layout_constraintHorizontal_bias="0" + app:layout_constraintWidth_percent="1.0" + app:layout_constraintWidth_max="wrap" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toEndOf="@+id/global_screenshot_preview" + app:layout_constraintEnd_toEndOf="parent"> + <LinearLayout + android:id="@+id/global_screenshot_actions" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + </HorizontalScrollView> + <ImageView + android:id="@+id/global_screenshot_animated_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center" + android:visibility="gone" + android:elevation="@dimen/screenshot_preview_elevation" + android:background="@drawable/screenshot_rounded_corners" + android:adjustViewBounds="true"/> + <include layout="@layout/global_screenshot_preview"/> + <FrameLayout + android:id="@+id/global_screenshot_dismiss_button" + android:layout_width="@dimen/screenshot_dismiss_button_tappable_size" + android:layout_height="@dimen/screenshot_dismiss_button_tappable_size" + android:elevation="7dp" + android:visibility="gone" + android:contentDescription="@string/screenshot_dismiss_ui_description" + app:layout_constraintStart_toEndOf="@+id/global_screenshot_preview" + app:layout_constraintEnd_toEndOf="@+id/global_screenshot_preview" + app:layout_constraintTop_toTopOf="@+id/global_screenshot_preview" + app:layout_constraintBottom_toTopOf="@+id/global_screenshot_preview"> + <ImageView + android:id="@+id/global_screenshot_dismiss_image" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="@dimen/screenshot_dismiss_button_margin" + android:src="@drawable/screenshot_cancel"/> + </FrameLayout> +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7f1763d2dec1..a7d176443c55 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -308,11 +308,11 @@ <dimen name="global_screenshot_x_scale">80dp</dimen> <dimen name="screenshot_bg_protection_height">242dp</dimen> <dimen name="screenshot_preview_elevation">6dp</dimen> - <dimen name="screenshot_offset_y">48dp</dimen> + <dimen name="screenshot_offset_y">32dp</dimen> <dimen name="screenshot_offset_x">16dp</dimen> <dimen name="screenshot_dismiss_button_tappable_size">48dp</dimen> <dimen name="screenshot_dismiss_button_margin">8dp</dimen> - <dimen name="screenshot_action_container_offset_y">32dp</dimen> + <dimen name="screenshot_action_container_offset_y">16dp</dimen> <dimen name="screenshot_action_container_corner_radius">10dp</dimen> <dimen name="screenshot_action_container_padding_vertical">6dp</dimen> <dimen name="screenshot_action_container_margin_horizontal">8dp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java index f1cb66784263..708002d5b946 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java @@ -27,8 +27,10 @@ import android.os.UserHandle; import android.util.Slog; import com.android.internal.os.BinderInternal; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpHandler; +import com.android.systemui.dump.LogBufferFreezer; import com.android.systemui.dump.SystemUIAuxiliaryDumpService; import java.io.FileDescriptor; @@ -40,21 +42,32 @@ public class SystemUIService extends Service { private final Handler mMainHandler; private final DumpHandler mDumpHandler; + private final BroadcastDispatcher mBroadcastDispatcher; + private final LogBufferFreezer mLogBufferFreezer; @Inject public SystemUIService( @Main Handler mainHandler, - DumpHandler dumpHandler) { + DumpHandler dumpHandler, + BroadcastDispatcher broadcastDispatcher, + LogBufferFreezer logBufferFreezer) { super(); mMainHandler = mainHandler; mDumpHandler = dumpHandler; + mBroadcastDispatcher = broadcastDispatcher; + mLogBufferFreezer = logBufferFreezer; } @Override public void onCreate() { super.onCreate(); + + // Start all of SystemUI ((SystemUIApplication) getApplication()).startServicesIfNeeded(); + // Finish initializing dump logic + mLogBufferFreezer.attach(mBroadcastDispatcher); + // For debugging RescueParty if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) { throw new RuntimeException(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java index 0327cb4b2919..c5faae0d703e 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java @@ -17,6 +17,7 @@ package com.android.systemui.bubbles; import android.service.notification.StatusBarNotification; + import com.android.internal.logging.UiEventLoggerImpl; /** @@ -31,6 +32,10 @@ public class BubbleLoggerImpl extends UiEventLoggerImpl implements BubbleLogger * @param e UI event */ public void log(Bubble b, UiEventEnum e) { + if (b.getEntry() == null) { + // Added from persistence -- TODO log this with specific event? + return; + } StatusBarNotification sbn = b.getEntry().getSbn(); logWithInstanceId(e, sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId()); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java index bea4ba776beb..8fd20517782f 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java @@ -22,6 +22,7 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME import android.app.Activity; import android.content.Context; +import android.content.pm.ShortcutInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -204,6 +205,8 @@ public class BubbleOverflowActivity extends Activity { } class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.ViewHolder> { + private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleOverflowAdapter" : TAG_BUBBLES; + private Context mContext; private Consumer<Bubble> mPromoteBubbleFromOverflow; private List<Bubble> mBubbles; @@ -282,11 +285,16 @@ class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.V } }); - Bubble.FlyoutMessage message = b.getFlyoutMessage(); - if (message != null && message.senderName != null) { - vh.textView.setText(message.senderName.toString()); + ShortcutInfo info = b.getEntry().getRanking().getShortcutInfo(); + if (info == null) { + Log.d(TAG, "ShortcutInfo required to bubble but none found for " + b); } else { - vh.textView.setText(b.getAppName()); + CharSequence label = info.getLabel(); + if (label == null) { + vh.textView.setText(b.getAppName()); + } else { + vh.textView.setText(label.toString()); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java index 942b9a74bb86..98a7cc23c67e 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java @@ -1037,6 +1037,11 @@ public class PhysicsAnimationLayout extends FrameLayout { if (view != null) { final SpringAnimation animation = (SpringAnimation) view.getTag(getTagIdForProperty(property)); + + if (animation == null) { + return; + } + final SpringForce animationSpring = animation.getSpring(); if (animationSpring == null) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index 2f917107cc23..26124f7f3285 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -251,7 +251,7 @@ internal class ControlHolder( component: ComponentName, @DeviceTypes.DeviceType deviceType: Int ): RenderInfo { - return RenderInfo.lookup(itemView.context, component, deviceType, true) + return RenderInfo.lookup(itemView.context, component, deviceType) } private fun applyRenderInfo(ri: RenderInfo) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt index 9b8c036659cd..15d15e8ffbc7 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt @@ -136,7 +136,7 @@ class ControlsRequestDialog @Inject constructor( } fun createDialog(label: CharSequence): Dialog { - val renderInfo = RenderInfo.lookup(this, component, control.deviceType, true) + val renderInfo = RenderInfo.lookup(this, component, control.deviceType) val frame = LayoutInflater.from(this).inflate(R.layout.controls_dialog, null).apply { requireViewById<ImageView>(R.id.icon).apply { setImageDrawable(renderInfo.icon) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index f979bbb7af35..f07f3168d246 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -29,6 +29,7 @@ import android.graphics.drawable.ClipDrawable import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.graphics.drawable.LayerDrawable +import android.graphics.drawable.StateListDrawable import android.service.controls.Control import android.service.controls.DeviceTypes import android.service.controls.actions.ControlAction @@ -75,7 +76,8 @@ class ControlViewHolder( DeviceTypes.TYPE_THERMOSTAT, DeviceTypes.TYPE_CAMERA ) - + private val ATTR_ENABLED = intArrayOf(android.R.attr.state_enabled) + private val ATTR_DISABLED = intArrayOf(-android.R.attr.state_enabled) const val MIN_LEVEL = 0 const val MAX_LEVEL = 10000 @@ -243,7 +245,7 @@ class ControlViewHolder( } internal fun applyRenderInfo(enabled: Boolean, offset: Int, animated: Boolean = true) { - val ri = RenderInfo.lookup(context, cws.componentName, deviceType, enabled, offset) + val ri = RenderInfo.lookup(context, cws.componentName, deviceType, offset) val fg = context.resources.getColorStateList(ri.foreground, context.theme) val newText = nextStatusText nextStatusText = "" @@ -394,7 +396,17 @@ class ControlViewHolder( icon.imageTintList = null icon.setImageIcon(it) } ?: run { - icon.setImageDrawable(drawable) + if (drawable is StateListDrawable) { + // Only reset the drawable if it is a different resource, as it will interfere + // with the image state and animation. + if (icon.drawable == null || !(icon.drawable is StateListDrawable)) { + icon.setImageDrawable(drawable) + } + val state = if (enabled) ATTR_ENABLED else ATTR_DISABLED + icon.setImageState(state, true) + } else { + icon.setImageDrawable(drawable) + } // do not color app icons if (deviceType != DeviceTypes.TYPE_ROUTINE) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt index ba331f459a0d..09d41bdd6927 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt @@ -28,16 +28,6 @@ import android.util.SparseArray import com.android.systemui.R -data class IconState(val disabledResourceId: Int, val enabledResourceId: Int) { - operator fun get(state: Boolean): Int { - return if (state) { - enabledResourceId - } else { - disabledResourceId - } - } -} - data class RenderInfo( val icon: Drawable, val foreground: Int, @@ -53,7 +43,6 @@ data class RenderInfo( context: Context, componentName: ComponentName, deviceType: Int, - enabled: Boolean, offset: Int = 0 ): RenderInfo { val key = if (offset > 0) { @@ -61,8 +50,7 @@ data class RenderInfo( } else deviceType val (fg, bg) = deviceColorMap.getValue(key) - val iconState = deviceIconMap.getValue(key) - val resourceId = iconState[enabled] + val resourceId = deviceIconMap.getValue(key) var icon: Drawable? if (resourceId == APP_ICON_ID) { icon = appIconMap.get(componentName) @@ -75,11 +63,10 @@ data class RenderInfo( icon = iconMap.get(resourceId) if (icon == null) { icon = context.resources.getDrawable(resourceId, null) - icon.mutate() iconMap.put(resourceId, icon) } } - return RenderInfo(icon!!, fg, bg) + return RenderInfo(icon!!.constantState.newDrawable(context.resources), fg, bg) } fun registerComponentIcon(componentName: ComponentName, icon: Drawable) { @@ -109,230 +96,67 @@ private val deviceColorMap = mapOf<Int, Pair<Int, Int>>( Pair(R.color.control_foreground, R.color.control_enabled_default_background) } -private val deviceIconMap = mapOf<Int, IconState>( - (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_off - ), - (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT_COOL) to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_ECO) to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_off - ), - DeviceTypes.TYPE_THERMOSTAT to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - DeviceTypes.TYPE_LIGHT to IconState( - R.drawable.ic_device_light_off, - R.drawable.ic_device_light_on - ), - DeviceTypes.TYPE_CAMERA to IconState( - R.drawable.ic_device_camera_off, - R.drawable.ic_device_camera_on - ), - DeviceTypes.TYPE_LOCK to IconState( - R.drawable.ic_device_lock_off, - R.drawable.ic_device_lock_on - ), - DeviceTypes.TYPE_SWITCH to IconState( - R.drawable.ic_device_switch_off, - R.drawable.ic_device_switch_on - ), - DeviceTypes.TYPE_OUTLET to IconState( - R.drawable.ic_device_outlet_off, - R.drawable.ic_device_outlet_on - ), - DeviceTypes.TYPE_VACUUM to IconState( - R.drawable.ic_device_vacuum_off, - R.drawable.ic_device_vacuum_on - ), - DeviceTypes.TYPE_MOP to IconState( - R.drawable.ic_device_mop_off, - R.drawable.ic_device_mop_on - ), - DeviceTypes.TYPE_AIR_FRESHENER to IconState( - R.drawable.ic_device_air_freshener_off, - R.drawable.ic_device_air_freshener_on - ), - DeviceTypes.TYPE_AIR_PURIFIER to IconState( - R.drawable.ic_device_air_purifier_off, - R.drawable.ic_device_air_purifier_on - ), - DeviceTypes.TYPE_FAN to IconState( - R.drawable.ic_device_fan_off, - R.drawable.ic_device_fan_on - ), - DeviceTypes.TYPE_HOOD to IconState( - R.drawable.ic_device_hood_off, - R.drawable.ic_device_hood_on - ), - DeviceTypes.TYPE_KETTLE to IconState( - R.drawable.ic_device_kettle_off, - R.drawable.ic_device_kettle_on - ), - DeviceTypes.TYPE_MICROWAVE to IconState( - R.drawable.ic_device_microwave_off, - R.drawable.ic_device_microwave_on - ), - DeviceTypes.TYPE_REMOTE_CONTROL to IconState( - R.drawable.ic_device_remote_control_off, - R.drawable.ic_device_remote_control_on - ), - DeviceTypes.TYPE_SET_TOP to IconState( - R.drawable.ic_device_set_top_off, - R.drawable.ic_device_set_top_on - ), - DeviceTypes.TYPE_STYLER to IconState( - R.drawable.ic_device_styler_off, - R.drawable.ic_device_styler_on - ), - DeviceTypes.TYPE_TV to IconState( - R.drawable.ic_device_tv_off, - R.drawable.ic_device_tv_on - ), - DeviceTypes.TYPE_WATER_HEATER to IconState( - R.drawable.ic_device_water_heater_off, - R.drawable.ic_device_water_heater_on - ), - DeviceTypes.TYPE_DISHWASHER to IconState( - R.drawable.ic_device_dishwasher_off, - R.drawable.ic_device_dishwasher_on - ), - DeviceTypes.TYPE_MULTICOOKER to IconState( - R.drawable.ic_device_multicooker_off, - R.drawable.ic_device_multicooker_on - ), - DeviceTypes.TYPE_SPRINKLER to IconState( - R.drawable.ic_device_sprinkler_off, - R.drawable.ic_device_sprinkler_on - ), - DeviceTypes.TYPE_WASHER to IconState( - R.drawable.ic_device_washer_off, - R.drawable.ic_device_washer_on - ), - DeviceTypes.TYPE_BLINDS to IconState( - R.drawable.ic_device_blinds_off, - R.drawable.ic_device_blinds_on - ), - DeviceTypes.TYPE_DRAWER to IconState( - R.drawable.ic_device_drawer_off, - R.drawable.ic_device_drawer_on - ), - DeviceTypes.TYPE_GARAGE to IconState( - R.drawable.ic_device_garage_off, - R.drawable.ic_device_garage_on - ), - DeviceTypes.TYPE_GATE to IconState( - R.drawable.ic_device_gate_off, - R.drawable.ic_device_gate_on - ), - DeviceTypes.TYPE_PERGOLA to IconState( - R.drawable.ic_device_pergola_off, - R.drawable.ic_device_pergola_on - ), - DeviceTypes.TYPE_WINDOW to IconState( - R.drawable.ic_device_window_off, - R.drawable.ic_device_window_on - ), - DeviceTypes.TYPE_VALVE to IconState( - R.drawable.ic_device_valve_off, - R.drawable.ic_device_valve_on - ), - DeviceTypes.TYPE_SECURITY_SYSTEM to IconState( - R.drawable.ic_device_security_system_off, - R.drawable.ic_device_security_system_on - ), - DeviceTypes.TYPE_REFRIGERATOR to IconState( - R.drawable.ic_device_refrigerator_off, - R.drawable.ic_device_refrigerator_on - ), - DeviceTypes.TYPE_DOORBELL to IconState( - R.drawable.ic_device_doorbell_off, - R.drawable.ic_device_doorbell_on - ), - DeviceTypes.TYPE_ROUTINE to IconState( - RenderInfo.APP_ICON_ID, - RenderInfo.APP_ICON_ID - ), - DeviceTypes.TYPE_AC_HEATER to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - DeviceTypes.TYPE_AC_UNIT to IconState( - R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - DeviceTypes.TYPE_COFFEE_MAKER to IconState( - R.drawable.ic_device_kettle_off, - R.drawable.ic_device_kettle_on - ), - DeviceTypes.TYPE_DEHUMIDIFIER to IconState( - R.drawable.ic_device_air_freshener_off, - R.drawable.ic_device_air_freshener_on - ), - DeviceTypes.TYPE_RADIATOR to IconState( +private val deviceIconMap = mapOf<Int, Int>( + (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ), - DeviceTypes.TYPE_STANDMIXER to IconState( - R.drawable.ic_device_cooking_off, - R.drawable.ic_device_cooking_on - ), - DeviceTypes.TYPE_DISPLAY to IconState( - R.drawable.ic_device_display_off, - R.drawable.ic_device_display_on - ), - DeviceTypes.TYPE_DRYER to IconState( - R.drawable.ic_device_washer_off, - R.drawable.ic_device_washer_on - ), - DeviceTypes.TYPE_MOWER to IconState( - R.drawable.ic_device_outdoor_garden_off, - R.drawable.ic_device_outdoor_garden_on - ), - DeviceTypes.TYPE_SHOWER to IconState( - R.drawable.ic_device_water_off, - R.drawable.ic_device_water_on - ), - DeviceTypes.TYPE_AWNING to IconState( - R.drawable.ic_device_pergola_off, - R.drawable.ic_device_pergola_on - ), - DeviceTypes.TYPE_CLOSET to IconState( - R.drawable.ic_device_drawer_off, - R.drawable.ic_device_drawer_on - ), - DeviceTypes.TYPE_CURTAIN to IconState( - R.drawable.ic_device_blinds_off, - R.drawable.ic_device_blinds_on - ), - DeviceTypes.TYPE_DOOR to IconState( - R.drawable.ic_device_door_off, - R.drawable.ic_device_door_on - ), - DeviceTypes.TYPE_SHUTTER to IconState( - R.drawable.ic_device_window_off, - R.drawable.ic_device_window_on - ), - DeviceTypes.TYPE_HEATER to IconState( + (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to + R.drawable.ic_device_thermostat, + (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to + R.drawable.ic_device_thermostat, + (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT_COOL) to + R.drawable.ic_device_thermostat, + (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_ECO) to R.drawable.ic_device_thermostat_off, - R.drawable.ic_device_thermostat_on - ) + DeviceTypes.TYPE_THERMOSTAT to R.drawable.ic_device_thermostat, + DeviceTypes.TYPE_LIGHT to R.drawable.ic_device_light, + DeviceTypes.TYPE_CAMERA to R.drawable.ic_device_camera, + DeviceTypes.TYPE_LOCK to R.drawable.ic_device_lock, + DeviceTypes.TYPE_SWITCH to R.drawable.ic_device_switch, + DeviceTypes.TYPE_OUTLET to R.drawable.ic_device_outlet, + DeviceTypes.TYPE_VACUUM to R.drawable.ic_device_vacuum, + DeviceTypes.TYPE_MOP to R.drawable.ic_device_mop, + DeviceTypes.TYPE_AIR_FRESHENER to R.drawable.ic_device_air_freshener, + DeviceTypes.TYPE_AIR_PURIFIER to R.drawable.ic_device_air_purifier, + DeviceTypes.TYPE_FAN to R.drawable.ic_device_fan, + DeviceTypes.TYPE_HOOD to R.drawable.ic_device_hood, + DeviceTypes.TYPE_KETTLE to R.drawable.ic_device_kettle, + DeviceTypes.TYPE_MICROWAVE to R.drawable.ic_device_microwave, + DeviceTypes.TYPE_REMOTE_CONTROL to R.drawable.ic_device_remote_control, + DeviceTypes.TYPE_SET_TOP to R.drawable.ic_device_set_top, + DeviceTypes.TYPE_STYLER to R.drawable.ic_device_styler, + DeviceTypes.TYPE_TV to R.drawable.ic_device_tv, + DeviceTypes.TYPE_WATER_HEATER to R.drawable.ic_device_water_heater, + DeviceTypes.TYPE_DISHWASHER to R.drawable.ic_device_dishwasher, + DeviceTypes.TYPE_MULTICOOKER to R.drawable.ic_device_multicooker, + DeviceTypes.TYPE_SPRINKLER to R.drawable.ic_device_sprinkler, + DeviceTypes.TYPE_WASHER to R.drawable.ic_device_washer, + DeviceTypes.TYPE_BLINDS to R.drawable.ic_device_blinds, + DeviceTypes.TYPE_DRAWER to R.drawable.ic_device_drawer, + DeviceTypes.TYPE_GARAGE to R.drawable.ic_device_garage, + DeviceTypes.TYPE_GATE to R.drawable.ic_device_gate, + DeviceTypes.TYPE_PERGOLA to R.drawable.ic_device_pergola, + DeviceTypes.TYPE_WINDOW to R.drawable.ic_device_window, + DeviceTypes.TYPE_VALVE to R.drawable.ic_device_valve, + DeviceTypes.TYPE_SECURITY_SYSTEM to R.drawable.ic_device_security_system, + DeviceTypes.TYPE_REFRIGERATOR to R.drawable.ic_device_refrigerator, + DeviceTypes.TYPE_DOORBELL to R.drawable.ic_device_doorbell, + DeviceTypes.TYPE_ROUTINE to RenderInfo.APP_ICON_ID, + DeviceTypes.TYPE_AC_HEATER to R.drawable.ic_device_thermostat, + DeviceTypes.TYPE_AC_UNIT to R.drawable.ic_device_thermostat, + DeviceTypes.TYPE_COFFEE_MAKER to R.drawable.ic_device_kettle, + DeviceTypes.TYPE_DEHUMIDIFIER to R.drawable.ic_device_air_freshener, + DeviceTypes.TYPE_RADIATOR to R.drawable.ic_device_thermostat, + DeviceTypes.TYPE_STANDMIXER to R.drawable.ic_device_cooking, + DeviceTypes.TYPE_DISPLAY to R.drawable.ic_device_display, + DeviceTypes.TYPE_DRYER to R.drawable.ic_device_washer, + DeviceTypes.TYPE_MOWER to R.drawable.ic_device_outdoor_garden, + DeviceTypes.TYPE_SHOWER to R.drawable.ic_device_water, + DeviceTypes.TYPE_AWNING to R.drawable.ic_device_pergola, + DeviceTypes.TYPE_CLOSET to R.drawable.ic_device_drawer, + DeviceTypes.TYPE_CURTAIN to R.drawable.ic_device_blinds, + DeviceTypes.TYPE_DOOR to R.drawable.ic_device_door, + DeviceTypes.TYPE_SHUTTER to R.drawable.ic_device_window, + DeviceTypes.TYPE_HEATER to R.drawable.ic_device_thermostat ).withDefault { - IconState( - R.drawable.ic_device_unknown_off, - R.drawable.ic_device_unknown_on - ) + R.drawable.ic_device_unknown } diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt index a4141b1b7cf0..bbb77504ec27 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt @@ -140,6 +140,20 @@ class DumpManager @Inject constructor() { } } + @Synchronized + fun freezeBuffers() { + for (buffer in buffers.values) { + buffer.dumpable.freeze() + } + } + + @Synchronized + fun unfreezeBuffers() { + for (buffer in buffers.values) { + buffer.dumpable.unfreeze() + } + } + private fun dumpDumpable( dumpable: RegisteredDumpable<Dumpable>, fd: FileDescriptor, @@ -174,3 +188,5 @@ private data class RegisteredDumpable<T>( val name: String, val dumpable: T ) + +private const val TAG = "DumpManager"
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt b/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt new file mode 100644 index 000000000000..29f464285e5d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt @@ -0,0 +1,69 @@ +/* + * 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.dump + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.UserHandle +import android.util.Log +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.util.concurrency.DelayableExecutor +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +class LogBufferFreezer constructor( + private val dumpManager: DumpManager, + @Main private val executor: DelayableExecutor, + private val freezeDuration: Long +) { + @Inject constructor( + dumpManager: DumpManager, + @Main executor: DelayableExecutor + ) : this(dumpManager, executor, TimeUnit.MINUTES.toMillis(5)) + + private var pendingToken: Runnable? = null + + fun attach(broadcastDispatcher: BroadcastDispatcher) { + broadcastDispatcher.registerReceiver( + object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + onBugreportStarted() + } + }, + IntentFilter("com.android.internal.intent.action.BUGREPORT_STARTED"), + executor, + UserHandle.ALL) + } + + private fun onBugreportStarted() { + pendingToken?.run() + + Log.i(TAG, "Freezing log buffers") + dumpManager.freezeBuffers() + + pendingToken = executor.executeDelayed({ + Log.i(TAG, "Unfreezing log buffers") + pendingToken = null + dumpManager.unfreezeBuffers() + }, freezeDuration) + } +} + +private const val TAG = "LogBufferFreezer"
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt index 342db346e14b..78d70877a90e 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt @@ -74,6 +74,9 @@ class LogBuffer( ) { private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque() + var frozen = false + private set + fun attach(dumpManager: DumpManager) { dumpManager.registerBuffer(name, this) } @@ -112,9 +115,11 @@ class LogBuffer( initializer: LogMessage.() -> Unit, noinline printer: LogMessage.() -> String ) { - val message = obtain(tag, level, printer) - initializer(message) - push(message) + if (!frozen) { + val message = obtain(tag, level, printer) + initializer(message) + push(message) + } } /** @@ -139,17 +144,16 @@ class LogBuffer( * * In general, you should call [log] or [document] instead of this method. */ + @Synchronized fun obtain( tag: String, level: LogLevel, printer: (LogMessage) -> String ): LogMessageImpl { - val message = synchronized(buffer) { - if (buffer.size > maxLogs - poolSize) { - buffer.removeFirst() - } else { - LogMessageImpl.create() - } + val message = when { + frozen -> LogMessageImpl.create() + buffer.size > maxLogs - poolSize -> buffer.removeFirst() + else -> LogMessageImpl.create() } message.reset(tag, level, System.currentTimeMillis(), printer) return message @@ -158,33 +162,58 @@ class LogBuffer( /** * Pushes a message into buffer, possibly evicting an older message if the buffer is full. */ + @Synchronized fun push(message: LogMessage) { - synchronized(buffer) { - if (buffer.size == maxLogs) { - Log.e(TAG, "LogBuffer $name has exceeded its pool size") - buffer.removeFirst() - } - buffer.add(message as LogMessageImpl) - if (logcatEchoTracker.isBufferLoggable(name, message.level) || - logcatEchoTracker.isTagLoggable(message.tag, message.level)) { - echoToLogcat(message) - } + if (frozen) { + return + } + if (buffer.size == maxLogs) { + Log.e(TAG, "LogBuffer $name has exceeded its pool size") + buffer.removeFirst() + } + buffer.add(message as LogMessageImpl) + if (logcatEchoTracker.isBufferLoggable(name, message.level) || + logcatEchoTracker.isTagLoggable(message.tag, message.level)) { + echoToLogcat(message) } } /** Converts the entire buffer to a newline-delimited string */ + @Synchronized fun dump(pw: PrintWriter, tailLength: Int) { - synchronized(buffer) { - val start = if (tailLength <= 0) { 0 } else { buffer.size - tailLength } + val start = if (tailLength <= 0) { 0 } else { buffer.size - tailLength } - for ((i, message) in buffer.withIndex()) { - if (i >= start) { - dumpMessage(message, pw) - } + for ((i, message) in buffer.withIndex()) { + if (i >= start) { + dumpMessage(message, pw) } } } + /** + * "Freezes" the contents of the buffer, making them immutable until [unfreeze] is called. + * Calls to [log], [document], [obtain], and [push] will not affect the buffer and will return + * dummy values if necessary. + */ + @Synchronized + fun freeze() { + if (!frozen) { + log(TAG, LogLevel.DEBUG, { str1 = name }, { "$str1 frozen" }) + frozen = true + } + } + + /** + * Undoes the effects of calling [freeze]. + */ + @Synchronized + fun unfreeze() { + if (frozen) { + log(TAG, LogLevel.DEBUG, { str1 = name }, { "$str1 unfrozen" }) + frozen = false + } + } + private fun dumpMessage(message: LogMessage, pw: PrintWriter) { pw.print(DATE_FORMAT.format(message.timestamp)) pw.print(" ") diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index 330a5c0dcad3..a94f6a87d58a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -35,7 +35,8 @@ data class MediaData( val packageName: String?, val token: MediaSession.Token?, val clickIntent: PendingIntent?, - val device: MediaDeviceData? + val device: MediaDeviceData?, + val notificationKey: String = "INVALID" ) /** State of a media action. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index cf7fbfa9461e..d94985703083 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -35,6 +35,8 @@ import com.android.internal.graphics.ColorUtils import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.notification.MediaNotificationProcessor +import com.android.systemui.statusbar.notification.NotificationEntryManager +import com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON import com.android.systemui.statusbar.notification.row.HybridGroupManager import com.android.systemui.util.Assert import com.android.systemui.util.Utils @@ -77,6 +79,8 @@ fun isMediaNotification(sbn: StatusBarNotification): Boolean { class MediaDataManager @Inject constructor( private val context: Context, private val mediaControllerFactory: MediaControllerFactory, + private val mediaTimeoutListener: MediaTimeoutListener, + private val notificationEntryManager: NotificationEntryManager, @Background private val backgroundExecutor: Executor, @Main private val foregroundExecutor: Executor ) { @@ -84,6 +88,12 @@ class MediaDataManager @Inject constructor( private val listeners: MutableSet<Listener> = mutableSetOf() private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap() + init { + mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean -> + setTimedOut(token, timedOut) } + addListener(mediaTimeoutListener) + } + fun onNotificationAdded(key: String, sbn: StatusBarNotification) { if (Utils.useQsMediaPlayer(context) && isMediaNotification(sbn)) { Assert.isMainThread() @@ -112,6 +122,16 @@ class MediaDataManager @Inject constructor( */ fun removeListener(listener: Listener) = listeners.remove(listener) + private fun setTimedOut(token: String, timedOut: Boolean) { + if (!timedOut) { + return + } + mediaEntries[token]?.let { + notificationEntryManager.removeNotification(it.notificationKey, null /* ranking */, + UNDEFINED_DISMISS_REASON) + } + } + private fun loadMediaDataInBg(key: String, sbn: StatusBarNotification) { val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) as MediaSession.Token? @@ -223,7 +243,7 @@ class MediaDataManager @Inject constructor( foregroundExecutor.execute { onMediaDataLoaded(key, MediaData(true, bgColor, app, smallIconDrawable, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, - notif.contentIntent, null)) + notif.contentIntent, null, key)) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt new file mode 100644 index 000000000000..92a1ab1b1871 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt @@ -0,0 +1,117 @@ +/* + * 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.media + +import android.media.session.MediaController +import android.media.session.PlaybackState +import android.os.SystemProperties +import android.util.Log +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState +import com.android.systemui.util.concurrency.DelayableExecutor +import java.util.concurrent.TimeUnit +import javax.inject.Inject +import javax.inject.Singleton + +private const val DEBUG = true +private const val TAG = "MediaTimeout" +private val PAUSED_MEDIA_TIMEOUT = SystemProperties + .getLong("debug.sysui.media_timeout", TimeUnit.MINUTES.toMillis(10)) + +/** + * Controller responsible for keeping track of playback states and expiring inactive streams. + */ +@Singleton +class MediaTimeoutListener @Inject constructor( + private val mediaControllerFactory: MediaControllerFactory, + @Main private val mainExecutor: DelayableExecutor +) : MediaDataManager.Listener { + + private val mediaListeners: MutableMap<String, PlaybackStateListener> = mutableMapOf() + + lateinit var timeoutCallback: (String, Boolean) -> Unit + + override fun onMediaDataLoaded(key: String, data: MediaData) { + if (mediaListeners.containsKey(key)) { + return + } + mediaListeners[key] = PlaybackStateListener(key, data) + } + + override fun onMediaDataRemoved(key: String) { + mediaListeners.remove(key)?.destroy() + } + + fun isTimedOut(key: String): Boolean { + return mediaListeners[key]?.timedOut ?: false + } + + private inner class PlaybackStateListener( + private val key: String, + data: MediaData + ) : MediaController.Callback() { + + var timedOut = false + + private val mediaController = mediaControllerFactory.create(data.token) + private var cancellation: Runnable? = null + + init { + mediaController.registerCallback(this) + } + + fun destroy() { + mediaController.unregisterCallback(this) + } + + override fun onPlaybackStateChanged(state: PlaybackState?) { + if (DEBUG) { + Log.v(TAG, "onPlaybackStateChanged: $state") + } + expireMediaTimeout(key, "playback state ativity - $state, $key") + + if (state == null || !isPlayingState(state.state)) { + if (DEBUG) { + Log.v(TAG, "schedule timeout for $key") + } + expireMediaTimeout(key, "PLAYBACK STATE CHANGED - $state") + cancellation = mainExecutor.executeDelayed({ + cancellation = null + if (DEBUG) { + Log.v(TAG, "Execute timeout for $key") + } + timedOut = true + timeoutCallback(key, timedOut) + }, PAUSED_MEDIA_TIMEOUT) + } else { + timedOut = false + timeoutCallback(key, timedOut) + } + } + + private fun expireMediaTimeout(mediaNotificationKey: String, reason: String) { + cancellation?.apply { + if (DEBUG) { + Log.v(TAG, + "media timeout cancelled for $mediaNotificationKey, reason: $reason") + } + run() + } + cancellation = null + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java index db7c6ad69d23..2863d08a75dc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java @@ -69,10 +69,14 @@ public class TileServices extends IQSService.Stub { mHost = host; mContext = mHost.getContext(); mBroadcastDispatcher = broadcastDispatcher; - mBroadcastDispatcher.registerReceiver(mRequestListeningReceiver, - new IntentFilter(TileService.ACTION_REQUEST_LISTENING)); mHandler = new Handler(looper); mMainHandler = new Handler(Looper.getMainLooper()); + mBroadcastDispatcher.registerReceiver( + mRequestListeningReceiver, + new IntentFilter(TileService.ACTION_REQUEST_LISTENING), + null, // Use the default Executor + UserHandle.ALL + ); } public Context getContext() { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 33d692f8e1e5..a9d3772a0fdb 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -64,7 +64,6 @@ import android.util.Slog; import android.view.Display; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.Surface; import android.view.SurfaceControl; import android.view.View; import android.view.ViewGroup; @@ -212,8 +211,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset private boolean mDirectionLTR = true; private boolean mOrientationPortrait = true; - private float mScreenshotOffsetXPx; - private float mScreenshotOffsetYPx; private float mCornerSizeX; private float mDismissDeltaY; @@ -273,8 +270,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset mDisplayMetrics = new DisplayMetrics(); mDisplay.getRealMetrics(mDisplayMetrics); - mScreenshotOffsetXPx = resources.getDimensionPixelSize(R.dimen.screenshot_offset_x); - mScreenshotOffsetYPx = resources.getDimensionPixelSize(R.dimen.screenshot_offset_y); mCornerSizeX = resources.getDimensionPixelSize(R.dimen.global_screenshot_x_scale); mDismissDeltaY = resources.getDimensionPixelSize(R.dimen.screenshot_dismissal_height_delta); @@ -448,12 +443,11 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset * Takes a screenshot of the current display and shows an animation. */ private void takeScreenshot(Consumer<Uri> finisher, Rect crop) { + // copy the input Rect, since SurfaceControl.screenshot can mutate it + Rect screenRect = new Rect(crop); int rot = mDisplay.getRotation(); int width = crop.width(); int height = crop.height(); - - Rect screenRect = new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels); - takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect); } @@ -483,12 +477,11 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset onConfigChanged(mContext.getResources().getConfiguration()); - if (mDismissAnimation != null && mDismissAnimation.isRunning()) { mDismissAnimation.cancel(); } // Start the post-screenshot animation - startAnimation(finisher, screenRect.width(), screenRect.height(), screenRect); + startAnimation(finisher, mScreenBitmap.getWidth(), mScreenBitmap.getHeight(), screenRect); } void takeScreenshot(Consumer<Uri> finisher, Runnable onComplete) { @@ -691,8 +684,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset /** * Starts the animation after taking the screenshot */ - private void startAnimation(final Consumer<Uri> finisher, int w, int h, - @Nullable Rect screenRect) { + private void startAnimation( + final Consumer<Uri> finisher, int bitmapWidth, int bitmapHeight, Rect screenRect) { // If power save is on, show a toast so there is some visual indication that a // screenshot has been taken. PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); @@ -700,21 +693,28 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset Toast.makeText(mContext, R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show(); } - mScreenshotAnimation = createScreenshotDropInAnimation(w, h, screenRect); - - saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() { - @Override - void onActionsReady(SavedImageData imageData) { - showUiOnActionsReady(imageData); - } - }); mScreenshotHandler.post(() -> { if (!mScreenshotLayout.isAttachedToWindow()) { mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams); } - mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this); + mScreenshotAnimatedView.setImageBitmap(mScreenBitmap); + mScreenshotPreview.setImageBitmap(mScreenBitmap); + + // make static preview invisible (from gone) so we can query its location on screen + mScreenshotPreview.setVisibility(View.INVISIBLE); mScreenshotHandler.post(() -> { + mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this); + + mScreenshotAnimation = + createScreenshotDropInAnimation(bitmapWidth, bitmapHeight, screenRect); + + saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() { + @Override + void onActionsReady(SavedImageData imageData) { + showUiOnActionsReady(imageData); + } + }); // Play the shutter sound to notify that we've taken a screenshot mCameraSound.play(MediaActionSound.SHUTTER_CLICK); @@ -726,18 +726,13 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset }); } - private AnimatorSet createScreenshotDropInAnimation(int width, int height, Rect bounds) { - float screenWidth = mDisplayMetrics.widthPixels; - float screenHeight = mDisplayMetrics.heightPixels; + private AnimatorSet createScreenshotDropInAnimation( + int bitmapWidth, int bitmapHeight, Rect bounds) { + Rect previewBounds = new Rect(); + mScreenshotPreview.getBoundsOnScreen(previewBounds); - int rotation = mContext.getDisplay().getRotation(); - float cornerScale; - if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) { - cornerScale = (mCornerSizeX / screenHeight); - } else { - cornerScale = (mCornerSizeX / screenWidth); - } - float currentScale = width / screenWidth; + float cornerScale = mCornerSizeX / (mOrientationPortrait ? bitmapWidth : bitmapHeight); + float currentScale = bounds.height() / (float) bitmapHeight; mScreenshotAnimatedView.setScaleX(currentScale); mScreenshotAnimatedView.setScaleY(currentScale); @@ -745,9 +740,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset mScreenshotAnimatedView.setPivotX(0); mScreenshotAnimatedView.setPivotY(0); - mScreenshotAnimatedView.setImageBitmap(mScreenBitmap); - mScreenshotPreview.setImageBitmap(mScreenBitmap); - AnimatorSet dropInAnimation = new AnimatorSet(); ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1); flashInAnimator.setDuration(SCREENSHOT_FLASH_IN_DURATION_MS); @@ -761,15 +753,9 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset flashOutAnimator.addUpdateListener(animation -> mScreenshotFlash.setAlpha((float) animation.getAnimatedValue())); + // animate from the current location, to the static preview location final PointF startPos = new PointF(bounds.centerX(), bounds.centerY()); - float finalX; - if (mDirectionLTR) { - finalX = mScreenshotOffsetXPx + screenWidth * cornerScale / 2f; - } else { - finalX = screenWidth - mScreenshotOffsetXPx - screenWidth * cornerScale / 2f; - } - float finalY = screenHeight - mScreenshotOffsetYPx - screenHeight * cornerScale / 2f; - final PointF finalPos = new PointF(finalX, finalY); + final PointF finalPos = new PointF(previewBounds.centerX(), previewBounds.centerY()); ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1); toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS); @@ -795,13 +781,13 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset if (t < xPositionPct) { float xCenter = MathUtils.lerp(startPos.x, finalPos.x, mFastOutSlowIn.getInterpolation(t / xPositionPct)); - mScreenshotAnimatedView.setX(xCenter - screenWidth * currentScaleX / 2f); + mScreenshotAnimatedView.setX(xCenter - bitmapWidth * currentScaleX / 2f); } else { - mScreenshotAnimatedView.setX(finalPos.x - screenWidth * currentScaleX / 2f); + mScreenshotAnimatedView.setX(finalPos.x - bitmapWidth * currentScaleX / 2f); } - float yCenter = MathUtils.lerp(startPos.y, finalPos.y, - mFastOutSlowIn.getInterpolation(t)); - mScreenshotAnimatedView.setY(yCenter - screenHeight * currentScaleY / 2f); + float yCenter = MathUtils.lerp( + startPos.y, finalPos.y, mFastOutSlowIn.getInterpolation(t)); + mScreenshotAnimatedView.setY(yCenter - bitmapHeight * currentScaleY / 2f); }); toCorner.addListener(new AnimatorListenerAdapter() { @@ -824,10 +810,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset super.onAnimationEnd(animation); mScreenshotAnimatedView.setScaleX(1); mScreenshotAnimatedView.setScaleY(1); - mScreenshotAnimatedView.setX(finalPos.x - width * cornerScale / 2f); - mScreenshotAnimatedView.setY(finalPos.y - height * cornerScale / 2f); - Rect bounds = new Rect(); - mDismissButton.getBoundsOnScreen(bounds); + mScreenshotAnimatedView.setX(finalPos.x - bounds.width() * cornerScale / 2f); + mScreenshotAnimatedView.setY(finalPos.y - bounds.height() * cornerScale / 2f); mScreenshotAnimatedView.setVisibility(View.GONE); mScreenshotPreview.setVisibility(View.VISIBLE); mDismissButton.setVisibility(View.VISIBLE); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 95aceed1126b..21810c0e7cf5 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -99,16 +99,19 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, private Handler mHandler; private KeyguardStateController mKeyguardStateController; + private WindowManagerProxy mWindowManagerProxy; + private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners = new ArrayList<>(); private SplitScreenTaskOrganizer mSplits = new SplitScreenTaskOrganizer(this); private DisplayChangeController.OnDisplayChangingListener mRotationController = - (display, fromRotation, toRotation, t) -> { - if (!mSplits.isSplitScreenSupported()) { + (display, fromRotation, toRotation, wct) -> { + if (!mSplits.isSplitScreenSupported() || mWindowManagerProxy == null) { return; } + WindowContainerTransaction t = new WindowContainerTransaction(); DisplayLayout displayLayout = new DisplayLayout(mDisplayController.getDisplayLayout(display)); SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits); @@ -127,6 +130,17 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (isSplitActive()) { WindowManagerProxy.applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t); } + if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) { + // Because sync transactions are serialized, its possible for an "older" + // bounds-change to get applied after a screen rotation. In that case, we + // want to actually defer on that rather than apply immediately. Of course, + // this means that the bounds may not change until after the rotation so + // the user might see some artifacts. This should be rare. + Slog.w(TAG, "Screen rotated while other operations were pending, this may" + + " result in some graphical artifacts."); + } else { + wct.merge(t, true /* transfer */); + } }; private final DividerImeController mImePositionProcessor; @@ -159,6 +173,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mRecentsOptionalLazy = recentsOptionalLazy; mForcedResizableController = new ForcedResizableInfoActivityController(context, this); mTransactionPool = transactionPool; + mWindowManagerProxy = new WindowManagerProxy(mTransactionPool, mHandler); mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler); } @@ -278,9 +293,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null); DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId()); mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout, - mImePositionProcessor); + mImePositionProcessor, mWindowManagerProxy); mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE); - mView.setMinimizedDockStack(mMinimized, mHomeStackResizable); + mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, null /* transaction */); final int size = dctx.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_thickness); final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE; @@ -303,7 +318,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, addDivider(configuration); if (mMinimized) { - mView.setMinimizedDockStack(true, mHomeStackResizable); + mView.setMinimizedDockStack(true, mHomeStackResizable, null /* transaction */); updateTouchable(); } mView.setHidden(isDividerHidden); @@ -327,11 +342,13 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (visible) { mView.enterSplitMode(mHomeStackResizable); // Update state because animations won't finish. - mView.setMinimizedDockStack(mMinimized, mHomeStackResizable); + mWindowManagerProxy.runInSync( + t -> mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, t)); + } else { mView.exitSplitMode(); - // un-minimize so that next entry triggers minimize anim. - mView.setMinimizedDockStack(false /* minimized */, mHomeStackResizable); + mWindowManagerProxy.runInSync( + t -> mView.setMinimizedDockStack(false, mHomeStackResizable, t)); } // Notify existence listeners synchronized (mDockedStackExistsListeners) { @@ -344,12 +361,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } } - void onSplitDismissed() { - updateVisibility(false /* visible */); - mMinimized = false; - removeDivider(); - } - /** Switch to minimized state if appropriate */ public void setMinimized(final boolean minimized) { if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible); @@ -405,7 +416,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } } updateTouchable(); - WindowOrganizer.applyTransaction(wct); + mWindowManagerProxy.applySyncTransaction(wct); } void setAdjustedForIme(boolean adjustedForIme) { @@ -501,7 +512,14 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, update(mDisplayController.getDisplayContext( mContext.getDisplayId()).getResources().getConfiguration()); // Set resizable directly here because applyEnterSplit already resizes home stack. - mHomeStackResizable = WindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout); + mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout); + } + + void startDismissSplit() { + mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, true /* dismissOrMaximize */); + updateVisibility(false /* visible */); + mMinimized = false; + removeDivider(); } void ensureMinimizedSplit() { @@ -530,6 +548,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, return mSplitLayout; } + WindowManagerProxy getWmProxy() { + return mWindowManagerProxy; + } + /** @return the container token for the secondary split root task. */ public WindowContainerToken getSecondaryRoot() { if (mSplits == null || mSplits.mSecondary == null) { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java index 1e0c07b1cd4c..aea87f2d1971 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java @@ -29,7 +29,6 @@ import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; -import android.window.WindowOrganizer; import androidx.annotation.Nullable; @@ -213,7 +212,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); } - WindowOrganizer.applyTransaction(wct); + mSplits.mDivider.getWmProxy().applySyncTransaction(wct); // Update all the adjusted-for-ime states if (!mPaused) { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index e349b5af5b2d..2271f6de194f 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -46,6 +46,7 @@ import android.view.VelocityTracker; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewConfiguration; +import android.view.ViewRootImpl; import android.view.ViewTreeObserver.InternalInsetsInfo; import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import android.view.WindowManager; @@ -138,7 +139,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, private final Rect mOtherInsetRect = new Rect(); private final Rect mLastResizeRect = new Rect(); private final Rect mTmpRect = new Rect(); - private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance(); + private WindowManagerProxy mWindowManagerProxy; private DividerWindowManager mWindowManager; private VelocityTracker mVelocityTracker; private FlingAnimationUtils mFlingAnimationUtils; @@ -360,13 +361,14 @@ public class DividerView extends FrameLayout implements OnTouchListener, public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState, DividerCallbacks callback, SplitScreenTaskOrganizer tiles, SplitDisplayLayout sdl, - DividerImeController imeController) { + DividerImeController imeController, WindowManagerProxy wmProxy) { mWindowManager = windowManager; mState = dividerState; mCallback = callback; mTiles = tiles; mSplitLayout = sdl; mImeController = imeController; + mWindowManagerProxy = wmProxy; if (mState.mRatioPositionBeforeMinimized == 0) { // Set the middle target as the initial state @@ -376,10 +378,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, } } - public WindowManagerProxy getWindowManagerProxy() { - return mWindowManagerProxy; - } - public Rect getNonMinimizedSplitScreenSecondaryBounds() { mOtherTaskRect.set(mSplitLayout.mSecondary); return mOtherTaskRect; @@ -519,7 +517,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget( mStartPosition, 0 /* velocity */, false /* hardDismiss */); - resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget); + resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget, + null /* transaction */); } break; case MotionEvent.ACTION_UP: @@ -608,7 +607,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME : snapTarget.taskPosition, - snapTarget)); + snapTarget, null /* transaction */)); Consumer<Boolean> endAction = cancelled -> { if (DEBUG) Slog.d(TAG, "End Fling " + cancelled + " min:" + mIsInMinimizeInteraction); final boolean wasMinimizeInteraction = mIsInMinimizeInteraction; @@ -716,7 +715,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, dismissOrMaximize = mDockSide == WindowManager.DOCKED_RIGHT || mDockSide == WindowManager.DOCKED_BOTTOM; } - mWindowManagerProxy.dismissOrMaximizeDocked(mTiles, dismissOrMaximize); + mWindowManagerProxy.dismissOrMaximizeDocked(mTiles, mSplitLayout, dismissOrMaximize); Transaction t = mTiles.getTransaction(); setResizeDimLayer(t, true /* primary */, 0f); setResizeDimLayer(t, false /* primary */, 0f); @@ -806,7 +805,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, mWindowManager.setTouchRegion(touchRegion); } - public void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable) { + void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable, + Transaction t) { mHomeStackResizable = isHomeStackResizable; updateDockSide(); if (!minimized) { @@ -840,9 +840,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, // Relayout to recalculate the divider shadow when minimizing requestLayout(); mIsInMinimizeInteraction = true; - resizeStackSurfaces(mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget()); + resizeStackSurfaces( + mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget(), t); } else { - resizeStackSurfaces(mSnapTargetBeforeMinimized); + resizeStackSurfaces(mSnapTargetBeforeMinimized, t); mIsInMinimizeInteraction = false; } } @@ -873,10 +874,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, * assigned to it. */ private SurfaceControl getWindowSurfaceControl() { - if (getViewRootImpl() == null) { + final ViewRootImpl root = getViewRootImpl(); + if (root == null) { return null; } - SurfaceControl out = getViewRootImpl().getSurfaceControl(); + SurfaceControl out = root.getSurfaceControl(); if (out != null && out.isValid()) { return out; } @@ -885,15 +887,13 @@ public class DividerView extends FrameLayout implements OnTouchListener, void exitSplitMode() { // Reset tile bounds - post(() -> { - final SurfaceControl sc = getWindowSurfaceControl(); - if (sc == null) { - return; - } - Transaction t = mTiles.getTransaction(); - t.hide(sc).apply(); - mTiles.releaseTransaction(t); - }); + final SurfaceControl sc = getWindowSurfaceControl(); + if (sc == null) { + return; + } + Transaction t = mTiles.getTransaction(); + t.hide(sc).apply(); + mTiles.releaseTransaction(t); int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; WindowManagerProxy.applyResizeSplits(midPos, mSplitLayout); } @@ -1049,8 +1049,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDividerSize); } - private void resizeStackSurfaces(SnapTarget taskSnapTarget) { - resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget); + private void resizeStackSurfaces(SnapTarget taskSnapTarget, Transaction t) { + resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget, t); } void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect otherRect) { @@ -1105,7 +1105,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, } } - void resizeStackSurfaces(int position, int taskPosition, SnapTarget taskSnapTarget) { + void resizeStackSurfaces(int position, int taskPosition, SnapTarget taskSnapTarget, + Transaction transaction) { if (mRemoved) { // This divider view has been removed so shouldn't have any additional influence. return; @@ -1123,7 +1124,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, mBackground.invalidate(); } - Transaction t = mTiles.getTransaction(); + final boolean ownTransaction = transaction == null; + final Transaction t = ownTransaction ? mTiles.getTransaction() : transaction; mLastResizeRect.set(mDockedRect); if (mHomeStackResizable && mIsInMinimizeInteraction) { calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide, @@ -1138,8 +1140,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, } resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect); - t.apply(); - mTiles.releaseTransaction(t); + if (ownTransaction) { + t.apply(); + mTiles.releaseTransaction(t); + } return; } @@ -1201,8 +1205,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position); float dimFraction = getDimFraction(position, closestDismissTarget); setResizeDimLayer(t, isDismissTargetPrimary(closestDismissTarget), dimFraction); - t.apply(); - mTiles.releaseTransaction(t); + if (ownTransaction) { + t.apply(); + mTiles.releaseTransaction(t); + } } private void applyExitAnimationParallax(Rect taskRect, int position) { @@ -1383,7 +1389,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, resizeStackSurfaces(calculatePositionForInsetBounds(), mSplitLayout.getSnapAlgorithm().getMiddleTarget().position, - mSplitLayout.getSnapAlgorithm().getMiddleTarget()); + mSplitLayout.getSnapAlgorithm().getMiddleTarget(), + null /* transaction */); } void onRecentsDrawn() { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java index c496d2280222..db324822994b 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java @@ -200,8 +200,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer { Log.d(TAG, " was in split, so this means leave it " + mPrimary.topActivityType + " " + mSecondary.topActivityType); } - WindowManagerProxy.applyDismissSplit(this, true /* dismissOrMaximize */); - mDivider.onSplitDismissed(); + mDivider.startDismissSplit(); } else if (!primaryIsEmpty && primaryWasEmpty && secondaryWasEmpty) { // Wasn't in split-mode (both were empty), but now that the primary split is // populated, we should fully enter split by moving everything else into secondary. diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java new file mode 100644 index 000000000000..1ff404677ea6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java @@ -0,0 +1,177 @@ +/* + * 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.stackdivider; + +import android.os.Handler; +import android.util.Slog; +import android.view.SurfaceControl; +import android.window.WindowContainerTransaction; +import android.window.WindowContainerTransactionCallback; +import android.window.WindowOrganizer; + +import androidx.annotation.NonNull; + +import com.android.systemui.TransactionPool; + +import java.util.ArrayList; + +/** + * Helper for serializing sync-transactions and corresponding callbacks. + */ +class SyncTransactionQueue { + private static final boolean DEBUG = Divider.DEBUG; + private static final String TAG = "SyncTransactionQueue"; + + // Just a little longer than the sync-engine timeout of 5s + private static final int REPLY_TIMEOUT = 5300; + + private final TransactionPool mTransactionPool; + private final Handler mHandler; + + // Sync Transactions currently don't support nesting or interleaving properly, so + // queue up transactions to run them serially. + private final ArrayList<SyncCallback> mQueue = new ArrayList<>(); + + private SyncCallback mInFlight = null; + private final ArrayList<TransactionRunnable> mRunnables = new ArrayList<>(); + + private final Runnable mOnReplyTimeout = () -> { + synchronized (mQueue) { + if (mInFlight != null && mQueue.contains(mInFlight)) { + Slog.w(TAG, "Sync Transaction timed-out: " + mInFlight.mWCT); + mInFlight.onTransactionReady(mInFlight.mId, new SurfaceControl.Transaction()); + } + } + }; + + SyncTransactionQueue(TransactionPool pool, Handler handler) { + mTransactionPool = pool; + mHandler = handler; + } + + /** + * Queues a sync transaction to be sent serially to WM. + */ + void queue(WindowContainerTransaction wct) { + SyncCallback cb = new SyncCallback(wct); + synchronized (mQueue) { + if (DEBUG) Slog.d(TAG, "Queueing up " + wct); + mQueue.add(cb); + if (mQueue.size() == 1) { + cb.send(); + } + } + } + + /** + * Queues a sync transaction only if there are already sync transaction(s) queued or in flight. + * Otherwise just returns without queueing. + * @return {@code true} if queued, {@code false} if not. + */ + boolean queueIfWaiting(WindowContainerTransaction wct) { + synchronized (mQueue) { + if (mQueue.isEmpty()) { + if (DEBUG) Slog.d(TAG, "Nothing in queue, so skip queueing up " + wct); + return false; + } + if (DEBUG) Slog.d(TAG, "Queue is non-empty, so queueing up " + wct); + SyncCallback cb = new SyncCallback(wct); + mQueue.add(cb); + if (mQueue.size() == 1) { + cb.send(); + } + } + return true; + } + + /** + * Runs a runnable in sync with sync transactions (ie. when the current in-flight transaction + * returns. If there are no transactions in-flight, runnable executes immediately. + */ + void runInSync(TransactionRunnable runnable) { + synchronized (mQueue) { + if (DEBUG) Slog.d(TAG, "Run in sync. mInFlight=" + mInFlight); + if (mInFlight != null) { + mRunnables.add(runnable); + return; + } + } + SurfaceControl.Transaction t = mTransactionPool.acquire(); + runnable.runWithTransaction(t); + t.apply(); + mTransactionPool.release(t); + } + + // Synchronized on mQueue + private void onTransactionReceived(@NonNull SurfaceControl.Transaction t) { + if (DEBUG) Slog.d(TAG, " Running " + mRunnables.size() + " sync runnables"); + for (int i = 0, n = mRunnables.size(); i < n; ++i) { + mRunnables.get(i).runWithTransaction(t); + } + mRunnables.clear(); + t.apply(); + t.close(); + } + + interface TransactionRunnable { + void runWithTransaction(SurfaceControl.Transaction t); + } + + private class SyncCallback extends WindowContainerTransactionCallback { + int mId = -1; + final WindowContainerTransaction mWCT; + + SyncCallback(WindowContainerTransaction wct) { + mWCT = wct; + } + + // Must be sychronized on mQueue + void send() { + if (mInFlight != null) { + throw new IllegalStateException("Sync Transactions must be serialized. In Flight: " + + mInFlight.mId + " - " + mInFlight.mWCT); + } + mInFlight = this; + if (DEBUG) Slog.d(TAG, "Sending sync transaction: " + mWCT); + mId = new WindowOrganizer().applySyncTransaction(mWCT, this); + if (DEBUG) Slog.d(TAG, " Sent sync transaction. Got id=" + mId); + mHandler.postDelayed(mOnReplyTimeout, REPLY_TIMEOUT); + } + + @Override + public void onTransactionReady(int id, + @androidx.annotation.NonNull SurfaceControl.Transaction t) { + mHandler.post(() -> { + synchronized (mQueue) { + if (mId != id) { + Slog.e(TAG, "Got an unexpected onTransactionReady. Expected " + + mId + " but got " + id); + return; + } + mInFlight = null; + mHandler.removeCallbacks(mOnReplyTimeout); + if (DEBUG) Slog.d(TAG, "onTransactionReady id=" + mId); + mQueue.remove(this); + onTransactionReceived(t); + if (!mQueue.isEmpty()) { + mQueue.get(0).send(); + } + } + }); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index 3027bd225216..c8361c63e960 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -25,9 +25,11 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.graphics.Rect; +import android.os.Handler; import android.os.RemoteException; import android.util.Log; import android.view.Display; +import android.view.SurfaceControl; import android.view.WindowManagerGlobal; import android.window.TaskOrganizer; import android.window.WindowContainerToken; @@ -35,6 +37,7 @@ import android.window.WindowContainerTransaction; import android.window.WindowOrganizer; import com.android.internal.annotations.GuardedBy; +import com.android.systemui.TransactionPool; import java.util.ArrayList; import java.util.List; @@ -49,8 +52,6 @@ public class WindowManagerProxy { private static final String TAG = "WindowManagerProxy"; private static final int[] HOME_AND_RECENTS = {ACTIVITY_TYPE_HOME, ACTIVITY_TYPE_RECENTS}; - private static final WindowManagerProxy sInstance = new WindowManagerProxy(); - @GuardedBy("mDockedRect") private final Rect mDockedRect = new Rect(); @@ -61,6 +62,8 @@ public class WindowManagerProxy { private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + private final SyncTransactionQueue mSyncTransactionQueue; + private final Runnable mSetTouchableRegionRunnable = new Runnable() { @Override public void run() { @@ -76,16 +79,13 @@ public class WindowManagerProxy { } }; - private WindowManagerProxy() { + WindowManagerProxy(TransactionPool transactionPool, Handler handler) { + mSyncTransactionQueue = new SyncTransactionQueue(transactionPool, handler); } - public static WindowManagerProxy getInstance() { - return sInstance; - } - - void dismissOrMaximizeDocked( - final SplitScreenTaskOrganizer tiles, final boolean dismissOrMaximize) { - mExecutor.execute(() -> applyDismissSplit(tiles, dismissOrMaximize)); + void dismissOrMaximizeDocked(final SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout, + final boolean dismissOrMaximize) { + mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize)); } public void setResizing(final boolean resizing) { @@ -163,7 +163,7 @@ public class WindowManagerProxy { * * @return whether the home stack is resizable */ - static boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) { + boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) { // Set launchtile first so that any stack created after // getAllStackInfos and before reparent (even if unlikely) are placed // correctly. @@ -174,6 +174,8 @@ public class WindowManagerProxy { if (rootTasks.isEmpty()) { return false; } + ActivityManager.RunningTaskInfo topHomeTask = null; + boolean homeIsTop = false; for (int i = rootTasks.size() - 1; i >= 0; --i) { final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i); // Only move resizeable task to split secondary. WM will just ignore this anyways... @@ -183,16 +185,25 @@ public class WindowManagerProxy { != WINDOWING_MODE_FULLSCREEN) { continue; } + // Since this iterates from bottom to top, update topHomeTask for every fullscreen task + // so it will be left with the status of the top one. + topHomeTask = isHomeOrRecentTask(rootTask) ? rootTask : null; wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */); } // Move the secondary split-forward. wct.reorder(tiles.mSecondary.token, true /* onTop */); boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct); - WindowOrganizer.applyTransaction(wct); + if (isHomeResizable && topHomeTask != null) { + // Translate/update-crop of secondary out-of-band with sync transaction -- Until BALST + // is enabled, this temporarily syncs the home surface position with offset until + // sync transaction finishes. + wct.setBoundsChangeTransaction(topHomeTask.token, tiles.mHomeBounds); + } + applySyncTransaction(wct); return isHomeResizable; } - private static boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) { + static boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) { final int atype = ti.configuration.windowConfiguration.getActivityType(); return atype == ACTIVITY_TYPE_HOME || atype == ACTIVITY_TYPE_RECENTS; } @@ -203,7 +214,8 @@ public class WindowManagerProxy { * split (thus resulting in the top of the secondary split becoming * fullscreen. {@code false} resolves the other way. */ - static void applyDismissSplit(SplitScreenTaskOrganizer tiles, boolean dismissOrMaximize) { + void applyDismissSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout, + boolean dismissOrMaximize) { // Set launch root first so that any task created after getChildContainers and // before reparent (pretty unlikely) are put into fullscreen. TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null); @@ -229,6 +241,7 @@ public class WindowManagerProxy { wct.reparent(primaryChildren.get(i).token, null /* parent */, true /* onTop */); } + boolean homeOnTop = false; // Don't need to worry about home tasks because they are already in the "proper" // order within the secondary split. for (int i = secondaryChildren.size() - 1; i >= 0; --i) { @@ -236,8 +249,31 @@ public class WindowManagerProxy { wct.reparent(ti.token, null /* parent */, true /* onTop */); if (isHomeOrRecentTask(ti)) { wct.setBounds(ti.token, null); + if (i == 0) { + homeOnTop = true; + } } } + if (homeOnTop) { + // Translate/update-crop of secondary out-of-band with sync transaction -- instead + // play this in sync with new home-app frame because until BALST is enabled this + // shows up on screen before the syncTransaction returns. + // We only have access to the secondary root surface, though, so in order to + // position things properly, we have to take into account the existing negative + // offset/crop of the minimized-home task. + final boolean landscape = layout.mDisplayLayout.isLandscape(); + final int posX = landscape ? layout.mSecondary.left - tiles.mHomeBounds.left + : layout.mSecondary.left; + final int posY = landscape ? layout.mSecondary.top + : layout.mSecondary.top - tiles.mHomeBounds.top; + final SurfaceControl.Transaction sft = new SurfaceControl.Transaction(); + sft.setPosition(tiles.mSecondarySurface, posX, posY); + final Rect crop = new Rect(0, 0, layout.mDisplayLayout.width(), + layout.mDisplayLayout.height()); + crop.offset(-posX, -posY); + sft.setWindowCrop(tiles.mSecondarySurface, crop); + wct.setBoundsChangeTransaction(tiles.mSecondary.token, sft); + } } else { // Maximize, so move non-home secondary split first for (int i = secondaryChildren.size() - 1; i >= 0; --i) { @@ -267,6 +303,29 @@ public class WindowManagerProxy { } // Reset focusable to true wct.setFocusable(tiles.mPrimary.token, true /* focusable */); - WindowOrganizer.applyTransaction(wct); + applySyncTransaction(wct); + } + + /** + * Utility to apply a sync transaction serially with other sync transactions. + * + * @see SyncTransactionQueue#queue + */ + void applySyncTransaction(WindowContainerTransaction wct) { + mSyncTransactionQueue.queue(wct); + } + + /** + * @see SyncTransactionQueue#queueIfWaiting + */ + boolean queueSyncTransactionIfWaiting(WindowContainerTransaction wct) { + return mSyncTransactionQueue.queueIfWaiting(wct); + } + + /** + * @see SyncTransactionQueue#runInSync + */ + void runInSync(SyncTransactionQueue.TransactionRunnable runnable) { + mSyncTransactionQueue.runInSync(runnable); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index db5329a8f952..217148df60e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; -import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON; import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK; import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER; import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK; @@ -36,7 +35,6 @@ import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.AsyncTask; -import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.provider.DeviceConfig; @@ -80,7 +78,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.TimeUnit; import dagger.Lazy; @@ -91,8 +88,6 @@ import dagger.Lazy; public class NotificationMediaManager implements Dumpable { private static final String TAG = "NotificationMediaManager"; public static final boolean DEBUG_MEDIA = false; - private static final long PAUSED_MEDIA_TIMEOUT = SystemProperties - .getLong("debug.sysui.media_timeout", TimeUnit.MINUTES.toMillis(10)); private final StatusBarStateController mStatusBarStateController = Dependency.get(StatusBarStateController.class); @@ -134,7 +129,6 @@ public class NotificationMediaManager implements Dumpable { private MediaController mMediaController; private String mMediaNotificationKey; private MediaMetadata mMediaMetadata; - private Runnable mMediaTimeoutCancellation; private BackDropView mBackdrop; private ImageView mBackdropFront; @@ -164,47 +158,11 @@ public class NotificationMediaManager implements Dumpable { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); } - if (mMediaTimeoutCancellation != null) { - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: media timeout cancelled"); - } - mMediaTimeoutCancellation.run(); - mMediaTimeoutCancellation = null; - } if (state != null) { if (!isPlaybackActive(state.getState())) { clearCurrentMediaNotification(); } findAndUpdateMediaNotifications(); - scheduleMediaTimeout(state); - } - } - - private void scheduleMediaTimeout(PlaybackState state) { - final NotificationEntry entry; - synchronized (mEntryManager) { - entry = mEntryManager.getActiveNotificationUnfiltered(mMediaNotificationKey); - } - if (entry != null) { - if (!isPlayingState(state.getState())) { - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: schedule timeout for " - + mMediaNotificationKey); - } - mMediaTimeoutCancellation = mMainExecutor.executeDelayed(() -> { - synchronized (mEntryManager) { - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: execute timeout for " - + mMediaNotificationKey); - } - if (mMediaNotificationKey == null) { - return; - } - mEntryManager.removeNotification(mMediaNotificationKey, null, - UNDEFINED_DISMISS_REASON); - } - }, PAUSED_MEDIA_TIMEOUT); - } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt new file mode 100644 index 000000000000..eb38073a85f7 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt @@ -0,0 +1,116 @@ +/* + * 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.dump + +import android.content.BroadcastReceiver +import android.content.IntentFilter +import android.os.UserHandle +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.capture +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.time.FakeSystemClock +import org.junit.Before +import org.junit.Test +import org.mockito.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +class LogBufferFreezerTest : SysuiTestCase() { + + lateinit var freezer: LogBufferFreezer + lateinit var receiver: BroadcastReceiver + + @Mock + lateinit var dumpManager: DumpManager + @Mock + lateinit var broadcastDispatcher: BroadcastDispatcher + @Captor + lateinit var receiverCaptor: ArgumentCaptor<BroadcastReceiver> + + val clock = FakeSystemClock() + val executor = FakeExecutor(clock) + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + freezer = LogBufferFreezer(dumpManager, executor, 500) + + freezer.attach(broadcastDispatcher) + + verify(broadcastDispatcher) + .registerReceiver( + capture(receiverCaptor), + any(IntentFilter::class.java), + eq(executor), + any(UserHandle::class.java)) + receiver = receiverCaptor.value + } + + @Test + fun testBuffersAreFrozenInResponseToBroadcast() { + // WHEN the bugreport intent is fired + receiver.onReceive(null, null) + + // THEN the buffers are frozen + verify(dumpManager).freezeBuffers() + } + + @Test + fun testBuffersAreUnfrozenAfterTimeout() { + // GIVEN that we've already frozen the buffers in response to a broadcast + receiver.onReceive(null, null) + verify(dumpManager).freezeBuffers() + + // WHEN the timeout expires + clock.advanceTime(501) + + // THEN the buffers are unfrozen + verify(dumpManager).unfreezeBuffers() + } + + @Test + fun testBuffersAreNotPrematurelyUnfrozen() { + // GIVEN that we received a broadcast 499ms ago (shortly before the timeout would expire) + receiver.onReceive(null, null) + verify(dumpManager).freezeBuffers() + clock.advanceTime(499) + + // WHEN we receive a second broadcast + receiver.onReceive(null, null) + + // THEN the buffers are frozen a second time + verify(dumpManager, times(2)).freezeBuffers() + + // THEN when we advance beyond the first timeout, nothing happens + clock.advanceTime(101) + verify(dumpManager, never()).unfreezeBuffers() + + // THEN only when we advance past the reset timeout window are the buffers unfrozen + clock.advanceTime(401) + verify(dumpManager).unfreezeBuffers() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index aa889a64c1b8..48e3b0a9d993 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -79,7 +79,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.addListener(mListener); mMediaData = new MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, - new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null); + new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, KEY); mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt new file mode 100644 index 000000000000..c21343cb5423 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt @@ -0,0 +1,130 @@ +/* + * 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.media + +import android.media.session.MediaController +import android.media.session.PlaybackState +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.mockito.capture +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyLong +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.`when` +import org.mockito.Mockito.clearInvocations +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit + +private const val KEY = "KEY" + +private fun <T> eq(value: T): T = Mockito.eq(value) ?: value +private fun <T> anyObject(): T { + return Mockito.anyObject<T>() +} + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class MediaTimeoutListenerTest : SysuiTestCase() { + + @Mock private lateinit var mediaControllerFactory: MediaControllerFactory + @Mock private lateinit var mediaController: MediaController + @Mock private lateinit var executor: DelayableExecutor + @Mock private lateinit var mediaData: MediaData + @Mock private lateinit var timeoutCallback: (String, Boolean) -> Unit + @Mock private lateinit var cancellationRunnable: Runnable + @Captor private lateinit var timeoutCaptor: ArgumentCaptor<Runnable> + @Captor private lateinit var mediaCallbackCaptor: ArgumentCaptor<MediaController.Callback> + @JvmField @Rule val mockito = MockitoJUnit.rule() + private lateinit var mediaTimeoutListener: MediaTimeoutListener + + @Before + fun setup() { + `when`(mediaControllerFactory.create(any())).thenReturn(mediaController) + `when`(executor.executeDelayed(any(), anyLong())).thenReturn(cancellationRunnable) + mediaTimeoutListener = MediaTimeoutListener(mediaControllerFactory, executor) + mediaTimeoutListener.timeoutCallback = timeoutCallback + } + + @Test + fun testOnMediaDataLoaded_registersPlaybackListener() { + mediaTimeoutListener.onMediaDataLoaded(KEY, mediaData) + verify(mediaController).registerCallback(capture(mediaCallbackCaptor)) + + // Ignores is same key + clearInvocations(mediaController) + mediaTimeoutListener.onMediaDataLoaded(KEY, mediaData) + verify(mediaController, never()).registerCallback(anyObject()) + } + + @Test + fun testOnMediaDataRemoved_unregistersPlaybackListener() { + mediaTimeoutListener.onMediaDataLoaded(KEY, mediaData) + mediaTimeoutListener.onMediaDataRemoved(KEY) + verify(mediaController).unregisterCallback(anyObject()) + + // Ignores duplicate requests + clearInvocations(mediaController) + mediaTimeoutListener.onMediaDataRemoved(KEY) + verify(mediaController, never()).unregisterCallback(anyObject()) + } + + @Test + fun testOnPlaybackStateChanged_schedulesTimeout_whenPaused() { + // Assuming we're registered + testOnMediaDataLoaded_registersPlaybackListener() + + mediaCallbackCaptor.value.onPlaybackStateChanged(PlaybackState.Builder() + .setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()) + verify(executor).executeDelayed(capture(timeoutCaptor), anyLong()) + } + + @Test + fun testOnPlaybackStateChanged_cancelsTimeout_whenResumed() { + // Assuming we're have a pending timeout + testOnPlaybackStateChanged_schedulesTimeout_whenPaused() + + mediaCallbackCaptor.value.onPlaybackStateChanged(PlaybackState.Builder() + .setState(PlaybackState.STATE_PLAYING, 0L, 0f).build()) + verify(cancellationRunnable).run() + } + + @Test + fun testTimeoutCallback_invokedIfTimeout() { + // Assuming we're have a pending timeout + testOnPlaybackStateChanged_schedulesTimeout_whenPaused() + + timeoutCaptor.value.run() + verify(timeoutCallback).invoke(eq(KEY), eq(true)) + } + + @Test + fun testIsTimedOut() { + mediaTimeoutListener.onMediaDataLoaded(KEY, mediaData) + assertThat(mediaTimeoutListener.isTimedOut(KEY)).isFalse() + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java index 2fc3d72c2672..53ed4cf12b2f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java @@ -18,13 +18,22 @@ package com.android.systemui.qs.external; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.IntentFilter; import android.os.Handler; import android.os.Looper; +import android.os.UserHandle; import android.service.quicksettings.Tile; +import android.service.quicksettings.TileService; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -50,7 +59,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -99,7 +107,7 @@ public class TileServicesTest extends SysuiTestCase { mTunerService, () -> mAutoTileManager, mDumpManager, - mBroadcastDispatcher, + mock(BroadcastDispatcher.class), Optional.of(mStatusBar), mQSLogger, mUiEventLogger); @@ -113,6 +121,14 @@ public class TileServicesTest extends SysuiTestCase { } @Test + public void testActiveTileListenerRegisteredOnAllUsers() { + ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class); + verify(mBroadcastDispatcher).registerReceiver(any(), captor.capture(), any(), eq( + UserHandle.ALL)); + assertTrue(captor.getValue().hasAction(TileService.ACTION_REQUEST_LISTENING)); + } + + @Test public void testRecalculateBindAllowance() { // Add some fake tiles. for (int i = 0; i < NUM_FAKES; i++) { @@ -125,10 +141,9 @@ public class TileServicesTest extends SysuiTestCase { } mTileService.recalculateBindAllowance(); for (int i = 0; i < NUM_FAKES; i++) { - Mockito.verify(mManagers.get(i), Mockito.times(1)).calculateBindPriority( - Mockito.anyLong()); + verify(mManagers.get(i), times(1)).calculateBindPriority(anyLong()); ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class); - Mockito.verify(mManagers.get(i), Mockito.times(1)).setBindAllowed(captor.capture()); + verify(mManagers.get(i), times(1)).setBindAllowed(captor.capture()); assertEquals("" + i + "th service", i >= (NUM_FAKES - TileServices.DEFAULT_MAX_BOUND), (boolean) captor.getValue()); @@ -142,7 +157,7 @@ public class TileServicesTest extends SysuiTestCase { for (int i = 0; i < NUM_FAKES; i++) { ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class); - Mockito.verify(mManagers.get(i), Mockito.times(2)).setBindAllowed(captor.capture()); + verify(mManagers.get(i), times(2)).setBindAllowed(captor.capture()); assertEquals("" + i + "th service", i >= (NUM_FAKES - TileServices.REDUCED_MAX_BOUND), (boolean) captor.getValue()); @@ -158,12 +173,12 @@ public class TileServicesTest extends SysuiTestCase { for (int i = 0; i < TileServices.DEFAULT_MAX_BOUND - 1; i++) { // Shouldn't get bind prioirities calculated when there are less than the max services. - Mockito.verify(mManagers.get(i), Mockito.never()).calculateBindPriority( - Mockito.anyLong()); + verify(mManagers.get(i), never()).calculateBindPriority( + anyLong()); // All should be bound since there are less than the max services. ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class); - Mockito.verify(mManagers.get(i), Mockito.times(1)).setBindAllowed(captor.capture()); + verify(mManagers.get(i), times(1)).setBindAllowed(captor.capture()); assertTrue(captor.getValue()); } diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 8ae30a5c6f92..d07a70c1af9b 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -34,7 +34,7 @@ java_defaults { ], libs: [ "framework-tethering.impl", - "framework-wifi-stubs-systemapi", + "framework-wifi", "unsupportedappusage", ], plugins: ["java_api_finder"], diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index 6c05b11258f0..c8becce7be82 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -30,11 +30,6 @@ java_sdk_library { ":framework-tethering-srcs", ], - // TODO(b/155480189) - Remove naming_scheme once references have been resolved. - // Temporary java_sdk_library component naming scheme to use to ease the transition from separate - // modules to java_sdk_library. - naming_scheme: "framework-modules", - jarjar_rules: "jarjar-rules.txt", installable: true, diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java index e095afea52ca..d084ca0966e8 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java @@ -17,8 +17,10 @@ package com.android.networkstack.tethering; import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.TETHER_PRIVILEGED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; @@ -240,15 +242,26 @@ public class TetheringService extends Service { return false; } + private boolean hasNetworkStackPermission() { + return checkCallingOrSelfPermission(NETWORK_STACK) + || checkCallingOrSelfPermission(PERMISSION_MAINLINE_NETWORK_STACK); + } + private boolean hasTetherPrivilegedPermission() { - return mService.checkCallingOrSelfPermission(TETHER_PRIVILEGED) == PERMISSION_GRANTED; + return checkCallingOrSelfPermission(TETHER_PRIVILEGED); + } + + private boolean checkCallingOrSelfPermission(final String permission) { + return mService.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; } private boolean hasTetherChangePermission(final String callerPkg, final boolean onlyAllowPrivileged) { + if (onlyAllowPrivileged && !hasNetworkStackPermission()) return false; + if (hasTetherPrivilegedPermission()) return true; - if (onlyAllowPrivileged || mTethering.isTetherProvisioningRequired()) return false; + if (mTethering.isTetherProvisioningRequired()) return false; int uid = Binder.getCallingUid(); // If callerPkg's uid is not same as Binder.getCallingUid(), diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java index 2fb7e607d0af..74df11370e50 100644 --- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -339,7 +339,7 @@ public class EthernetTetheringTest { private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception { return enableEthernetTethering(iface, new TetheringRequest.Builder(TETHERING_ETHERNET) - .setExemptFromEntitlementCheck(true).build()); + .setShouldShowEntitlementUi(false).build()); } private int getMTU(TestNetworkInterface iface) throws SocketException { @@ -510,7 +510,7 @@ public class EthernetTetheringTest { LinkAddress clientAddr = client == null ? null : new LinkAddress(client); return new TetheringRequest.Builder(TETHERING_ETHERNET) .setStaticIpv4Addresses(localAddr, clientAddr) - .setExemptFromEntitlementCheck(true).build(); + .setShouldShowEntitlementUi(false).build(); } private void assertInvalidStaticIpv4Request(String iface, String local, String client) diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index fccc6902e365..45c7b656e28f 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -60,7 +60,7 @@ java_defaults { "framework-minus-apex", "framework-res", "framework-tethering.impl", - "framework-wifi-stubs-module_libs_api", + "framework-wifi.stubs.module_lib", ], jni_libs: [ // For mockito extended diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java index f4a566659896..22d894bf471e 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java @@ -274,21 +274,32 @@ public final class TetheringServiceTest { }); } + private void runStartTetheringAndVerifyNoPermission(final TestTetheringResult result) + throws Exception { + final TetheringRequestParcel request = new TetheringRequestParcel(); + request.tetheringType = TETHERING_WIFI; + request.exemptFromEntitlementCheck = true; + mTetheringConnector.startTethering(request, TEST_CALLER_PKG, result); + result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); + verifyNoMoreInteractionsForTethering(); + } + @Test - public void testStartTetheringWithExemptFromEntitlementCheck() throws Exception { + public void testFailToBypassEntitlementWithoutNeworkStackPermission() throws Exception { final TetheringRequestParcel request = new TetheringRequestParcel(); request.tetheringType = TETHERING_WIFI; request.exemptFromEntitlementCheck = true; + runAsNoPermission((result) -> { + runStartTetheringAndVerifyNoPermission(result); + }); + runAsTetherPrivileged((result) -> { - runStartTethering(result, request); - verifyNoMoreInteractionsForTethering(); + runStartTetheringAndVerifyNoPermission(result); }); runAsWriteSettings((result) -> { - mTetheringConnector.startTethering(request, TEST_CALLER_PKG, result); - result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - verifyNoMoreInteractionsForTethering(); + runStartTetheringAndVerifyNoPermission(result); }); } diff --git a/services/Android.bp b/services/Android.bp index 882085a7d0ba..00676e332656 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -87,7 +87,7 @@ java_library { libs: [ "android.hidl.manager-V1.0-java", - "framework-tethering-stubs-module_libs_api", + "framework-tethering.stubs.module_lib", ], // Uncomment to enable output of certain warnings (deprecated, unchecked) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 22b082f84a84..7f912a4fc1ce 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -16,6 +16,7 @@ package com.android.server.accessibility; +import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED; import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; import static android.view.accessibility.AccessibilityManager.ShortcutType; @@ -542,12 +543,56 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE), intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)); } + } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) { + synchronized (mLock) { + restoreLegacyDisplayMagnificationNavBarIfNeededLocked( + intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE), + intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, + 0)); + } } } } }, UserHandle.ALL, intentFilter, null, null); } + // Called only during settings restore; currently supports only the owner user + // TODO: b/22388012 + private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting, + int restoreFromSdkInt) { + if (restoreFromSdkInt >= Build.VERSION_CODES.R) { + return; + } + + boolean displayMagnificationNavBarEnabled; + try { + displayMagnificationNavBarEnabled = Integer.parseInt(newSetting) == 1; + } catch (NumberFormatException e) { + Slog.w(LOG_TAG, "number format is incorrect" + e); + return; + } + + final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); + final Set<String> targetsFromSetting = new ArraySet<>(); + readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, + userState.mUserId, targetsFromSetting, str -> str); + final boolean targetsContainMagnification = targetsFromSetting.contains( + MAGNIFICATION_CONTROLLER_NAME); + if (targetsContainMagnification == displayMagnificationNavBarEnabled) { + return; + } + + if (displayMagnificationNavBarEnabled) { + targetsFromSetting.add(MAGNIFICATION_CONTROLLER_NAME); + } else { + targetsFromSetting.remove(MAGNIFICATION_CONTROLLER_NAME); + } + persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, + userState.mUserId, targetsFromSetting, str -> str); + readAccessibilityButtonTargetsLocked(userState); + onUserStateChangedLocked(userState); + } + @Override public long addClient(IAccessibilityManagerClient callback, int userId) { synchronized (mLock) { diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java index 687b75a8b949..e7a43b75f9d5 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java +++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java @@ -40,7 +40,6 @@ import com.android.server.autofill.ui.InlineFillUi; import com.android.server.inputmethod.InputMethodManagerInternal; import java.lang.ref.WeakReference; -import java.util.Collections; import java.util.Optional; import java.util.function.Consumer; @@ -209,18 +208,9 @@ final class AutofillInlineSuggestionsRequestSession { if (mDestroyed || mResponseCallback == null) { return; } - if (!mImeInputStarted && mPreviousResponseIsNotEmpty) { - // 1. if previous response is not empty, and IME is just disconnected from the view, - // then send empty response to make sure existing responses don't stick around. - // Although the inline suggestions should disappear when IME hides which removes them - // from the view hierarchy, but we still send an empty response to indicate that the - // previous suggestions are invalid now. - if (sVerbose) Slog.v(TAG, "Send empty inline response"); - updateResponseToImeUncheckLocked(new InlineSuggestionsResponse(Collections.EMPTY_LIST)); - mPreviousResponseIsNotEmpty = false; - } else if (mImeInputViewStarted && mInlineFillUi != null && match(mAutofillId, + if (mImeInputViewStarted && mInlineFillUi != null && match(mAutofillId, mImeCurrentFieldId)) { - // 2. if IME is visible, and response is not null, send the response + // if IME is visible, and response is not null, send the response InlineSuggestionsResponse response = mInlineFillUi.getInlineSuggestionsResponse(); boolean isEmptyResponse = response.getInlineSuggestions().isEmpty(); if (isEmptyResponse && !mPreviousResponseIsNotEmpty) { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ffdb9c83c805..642526d13aff 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -3852,6 +3852,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState for (int i = 0; i < responseCount; i++) { if (mResponses.keyAt(i) > lastResponseId) { lastResponseIdx = i; + lastResponseId = mResponses.keyAt(i); } } } diff --git a/services/core/Android.bp b/services/core/Android.bp index a95a0c2eaf28..9e8a8727dc36 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -99,7 +99,7 @@ java_library_static { "android.hardware.vibrator-java", "android.net.ipsec.ike.stubs.module_lib", "app-compat-annotations", - "framework-tethering-stubs-module_libs_api", + "framework-tethering.stubs.module_lib", "service-permission-stubs", ], diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index e77458cc955a..fd7abfa65c86 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -239,7 +239,10 @@ public class PackageWatchdog { mIsPackagesReady = true; mHealthCheckController.setCallbacks(packageName -> onHealthCheckPassed(packageName), packages -> onSupportedPackages(packages), - () -> syncRequestsAsync()); + () -> { + syncRequestsAsync(); + mSyncRequired = true; + }); setPropertyChangedListenerLocked(); updateConfigs(); registerConnectivityModuleHealthListener(); @@ -255,7 +258,6 @@ public class PackageWatchdog { */ public void registerHealthObserver(PackageHealthObserver observer) { synchronized (mLock) { - mSyncRequired = true; ObserverInternal internalObserver = mAllObservers.get(observer.getName()); if (internalObserver != null) { internalObserver.registeredObserver = observer; @@ -642,7 +644,8 @@ public class PackageWatchdog { synchronized (mLock) { if (mIsPackagesReady) { Set<String> packages = getPackagesPendingHealthChecksLocked(); - if (!packages.equals(mRequestedHealthCheckPackages) || mSyncRequired) { + if (mSyncRequired || !packages.equals(mRequestedHealthCheckPackages) + || packages.isEmpty()) { syncRequired = true; mRequestedHealthCheckPackages = packages; } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index ee0f71b9e982..b5aec8e401eb 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -376,6 +376,7 @@ class StorageManagerService extends IStorageManager.Stub private class WatchedLockedUsers { private int[] users = EmptyArray.INT; public WatchedLockedUsers() { + invalidateIsUserUnlockedCache(); } public void append(int userId) { users = ArrayUtils.appendInt(users, userId); @@ -1134,6 +1135,8 @@ class StorageManagerService extends IStorageManager.Stub Slog.wtf(TAG, e); } + onKeyguardStateChanged(false); + mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget(); } diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index 197a2cef0a62..74bb7d7e90f1 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -198,12 +198,12 @@ public class SystemServiceManager { Slog.i(TAG, "Starting phase " + mCurrentPhase); try { - t.traceBegin("OnBootPhase " + phase); + t.traceBegin("OnBootPhase_" + phase); final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); long time = SystemClock.elapsedRealtime(); - t.traceBegin("OnBootPhase " + service.getClass().getName()); + t.traceBegin("OnBootPhase_" + phase + "_" + service.getClass().getName()); try { service.onBootPhase(mCurrentPhase); } catch (Exception ex) { @@ -332,7 +332,7 @@ public class SystemServiceManager { } continue; } - t.traceBegin("ssm.on" + onWhat + "User-" + curUserId + " " + serviceName); + t.traceBegin("ssm.on" + onWhat + "User-" + curUserId + "_" + serviceName); long time = SystemClock.elapsedRealtime(); try { switch (onWhat) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 5046070647d6..c5c3cafa8813 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2460,16 +2460,22 @@ public final class ActiveServices { && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) { userId = 0; smap = getServiceMapLocked(0); - ResolveInfo rInfoForUserId0 = - mAm.getPackageManagerInternalLocked().resolveService(service, - resolvedType, flags, userId, callingUid); - if (rInfoForUserId0 == null) { - Slog.w(TAG_SERVICE, - "Unable to resolve service " + service + " U=" + userId - + ": not found"); - return null; + // Bypass INTERACT_ACROSS_USERS permission check + final long token = Binder.clearCallingIdentity(); + try { + ResolveInfo rInfoForUserId0 = + mAm.getPackageManagerInternalLocked().resolveService(service, + resolvedType, flags, userId, callingUid); + if (rInfoForUserId0 == null) { + Slog.w(TAG_SERVICE, + "Unable to resolve service " + service + " U=" + userId + + ": not found"); + return null; + } + sInfo = rInfoForUserId0.serviceInfo; + } finally { + Binder.restoreCallingIdentity(token); } - sInfo = rInfoForUserId0.serviceInfo; } sInfo = new ServiceInfo(sInfo); sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a4e45cd334bf..caaa8371af53 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -18900,30 +18900,8 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) { - // We can find ourselves needing to check Uri permissions while - // already holding the WM lock, which means reaching back here for - // the AM lock would cause an inversion. The WM team has requested - // that we use the strategy below instead of shifting where Uri - // grants are calculated. - - // Since we could also arrive here while holding the AM lock, we - // can't always delegate the call through the handler, and we need - // to delicately dance between the deadlocks. - if (Thread.currentThread().holdsLock(ActivityManagerService.this)) { - return ActivityManagerService.this.checkContentProviderUriPermission(uri, - userId, callingUid, modeFlags); - } else { - final CompletableFuture<Integer> res = new CompletableFuture<>(); - mHandler.post(() -> { - res.complete(ActivityManagerService.this.checkContentProviderUriPermission(uri, - userId, callingUid, modeFlags)); - }); - try { - return res.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } + return ActivityManagerService.this.checkContentProviderUriPermission(uri, + userId, callingUid, modeFlags); } @Override diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index a0876c063fb3..061972c5723a 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -290,9 +290,10 @@ public class AuthService extends SystemService { // The permission check should be restored once Android Keystore no longer invokes this // method from inside app processes. + final int callingUserId = UserHandle.getCallingUserId(); final long identity = Binder.clearCallingIdentity(); try { - return mBiometricService.getAuthenticatorIds(); + return mBiometricService.getAuthenticatorIds(callingUserId); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 4ddfe1b6e2d2..540c6ff09c9d 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -879,13 +879,13 @@ public class BiometricService extends SystemService { } @Override // Binder call - public long[] getAuthenticatorIds() { + public long[] getAuthenticatorIds(int callingUserId) { checkInternalPermission(); final List<Long> ids = new ArrayList<>(); for (AuthenticatorWrapper authenticator : mAuthenticators) { try { - final long id = authenticator.impl.getAuthenticatorId(); + final long id = authenticator.impl.getAuthenticatorId(callingUserId); if (Utils.isAtLeastStrength(authenticator.getActualStrength(), Authenticators.BIOMETRIC_STRONG) && id != 0) { ids.add(id); diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index 5a6ab4e59424..75452ea5fb61 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -1250,9 +1250,8 @@ public abstract class BiometricServiceBase extends SystemService /*** * @return authenticator id for the calling user */ - protected long getAuthenticatorId() { - final int userId = getUserOrWorkProfileId(null /* clientPackage */, - UserHandle.getCallingUserId()); + protected long getAuthenticatorId(int callingUserId) { + final int userId = getUserOrWorkProfileId(null /* clientPackage */, callingUserId); return mAuthenticatorIds.getOrDefault(userId, 0L); } diff --git a/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java index 9d8fcc3421cb..405c54e3be63 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java @@ -74,7 +74,7 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public long getAuthenticatorId() throws RemoteException { - return mFaceService.getAuthenticatorId(); + public long getAuthenticatorId(int callingUserId) throws RemoteException { + return mFaceService.getAuthenticatorId(callingUserId); } } diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index ad73b6491697..72e1bbbcba60 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -608,9 +608,9 @@ public class FaceService extends BiometricServiceBase { } @Override // Binder call - public long getAuthenticatorId() { + public long getAuthenticatorId(int callingUserId) { checkPermission(USE_BIOMETRIC_INTERNAL); - return FaceService.this.getAuthenticatorId(); + return FaceService.this.getAuthenticatorId(callingUserId); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java index 4604752408ba..61ddadadd784 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java @@ -74,7 +74,7 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub } @Override - public long getAuthenticatorId() throws RemoteException { - return mFingerprintService.getAuthenticatorId(); + public long getAuthenticatorId(int callingUserId) throws RemoteException { + return mFingerprintService.getAuthenticatorId(callingUserId); } } diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index d90f3afd8dca..6b7ba6a56d82 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -412,9 +412,9 @@ public class FingerprintService extends BiometricServiceBase { } @Override // Binder call - public long getAuthenticatorId() { + public long getAuthenticatorId(int callingUserId) { checkPermission(USE_BIOMETRIC_INTERNAL); - return FingerprintService.this.getAuthenticatorId(); + return FingerprintService.this.getAuthenticatorId(callingUserId); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java index 6789a12d065f..03818ed94926 100644 --- a/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java @@ -67,7 +67,7 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public long getAuthenticatorId() throws RemoteException { + public long getAuthenticatorId(int callingUserId) throws RemoteException { return 0; } } diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java index 3d4efe614e1d..817902d9d566 100644 --- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java +++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java @@ -182,7 +182,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { }, integrityVerificationFilter, /* broadcastPermission= */ null, - /* scheduler= */ null); + mHandler); } @Override diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java index 53205add0b38..d6b98e2de901 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java @@ -44,7 +44,6 @@ import java.util.Objects; /** * Maintains a connection to a particular {@link MediaRoute2ProviderService}. */ -// TODO: Need to revisit the bind/unbind/connect/disconnect logic in this class. final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider implements ServiceConnection { private static final String TAG = "MR2ProviderSvcProxy"; @@ -265,8 +264,6 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider if (DEBUG) { Slog.d(TAG, this + ": Service binding died"); } - // TODO: Investigate whether it tries to bind endlessly when the service is - // badly implemented. if (shouldBind()) { unbind(); bind(); diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index c65800a17f82..75a89a213052 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -1026,7 +1026,8 @@ class MediaRouter2ServiceImpl { mHandler = new UserHandler(MediaRouter2ServiceImpl.this, this); } - // TODO: This assumes that only one router exists in a package. Is it true? + // TODO: This assumes that only one router exists in a package. + // Do this in Android S or later. RouterRecord findRouterRecordLocked(String packageName) { for (RouterRecord routerRecord : mRouterRecords) { if (TextUtils.equals(routerRecord.mPackageName, packageName)) { @@ -1121,7 +1122,6 @@ class MediaRouter2ServiceImpl { private final UserRecord mUserRecord; private final MediaRoute2ProviderWatcher mWatcher; - //TODO: Make this thread-safe. private final SystemMediaRoute2Provider mSystemProvider; private final ArrayList<MediaRoute2Provider> mRouteProviders = new ArrayList<>(); @@ -1153,7 +1153,6 @@ class MediaRouter2ServiceImpl { private void stop() { if (mRunning) { mRunning = false; - //TODO: may unselect routes mWatcher.stop(); // also stops all providers } } @@ -1386,7 +1385,6 @@ class MediaRouter2ServiceImpl { final String providerId = route.getProviderId(); final MediaRoute2Provider provider = findProvider(providerId); - // TODO: Remove this null check when the mMediaProviders are referenced only in handler. if (provider == null) { return; } @@ -1405,7 +1403,6 @@ class MediaRouter2ServiceImpl { final String providerId = route.getProviderId(); final MediaRoute2Provider provider = findProvider(providerId); - // TODO: Remove this null check when the mMediaProviders are referenced only in handler. if (provider == null) { return; } @@ -1425,7 +1422,6 @@ class MediaRouter2ServiceImpl { final String providerId = route.getProviderId(); final MediaRoute2Provider provider = findProvider(providerId); - // TODO: Remove this null check when the mMediaProviders are referenced only in handler. if (provider == null) { return; } @@ -1641,8 +1637,8 @@ class MediaRouter2ServiceImpl { // TODO: Notify router too when the related callback is introduced. } - // TODO: Find a way to prevent providers from notifying error on random uniqueRequestId. - // Solutions can be: + // TODO(b/157873556): Find a way to prevent providers from notifying error on random reqID. + // Possible solutions can be: // 1) Record the other type of requests too (not only session creation request) // 2) Throw exception on providers when they try to notify error on // random uniqueRequestId. diff --git a/services/core/java/com/android/server/notification/BubbleExtractor.java b/services/core/java/com/android/server/notification/BubbleExtractor.java index 0fa339f65cdb..fd92c4c82f24 100644 --- a/services/core/java/com/android/server/notification/BubbleExtractor.java +++ b/services/core/java/com/android/server/notification/BubbleExtractor.java @@ -78,6 +78,7 @@ public class BubbleExtractor implements NotificationSignalExtractor { boolean canPresentAsBubble = canPresentAsBubble(record) && !mActivityManager.isLowRamDevice() && record.isConversation() + && record.getShortcutInfo() != null && (record.getNotification().flags & FLAG_FOREGROUND_SERVICE) == 0; if (!mConfig.bubblesEnabled() diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 6ae58ec7feea..9d3385f20695 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1952,7 +1952,8 @@ public class NotificationManagerService extends SystemService { mRankingHandler, mZenModeHelper, new NotificationChannelLoggerImpl(), - mAppOps); + mAppOps, + new SysUiStatsEvent.BuilderFactory()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, @@ -6802,9 +6803,13 @@ public class NotificationManagerService extends SystemService { boolean hasValidVibrate = false; boolean hasValidSound = false; boolean sentAccessibilityEvent = false; - // If the notification will appear in the status bar, it should send an accessibility - // event - if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) { + + // If the notification will appear in the status bar, it should send an accessibility event + final boolean suppressedByDnd = record.isIntercepted() + && (record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_STATUS_BAR) != 0; + if (!record.isUpdate + && record.getImportance() > IMPORTANCE_MIN + && !suppressedByDnd) { sendAccessibilityEvent(notification, record.getSbn().getPackageName()); sentAccessibilityEvent = true; } diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 77b030f9ed0d..e472e3097777 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -140,6 +140,7 @@ public class PreferencesHelper implements RankingConfig { * fields. */ private static final int DEFAULT_LOCKED_APP_FIELDS = 0; + private final SysUiStatsEvent.BuilderFactory mStatsEventBuilderFactory; /** * All user-lockable fields for a given application. @@ -171,13 +172,15 @@ public class PreferencesHelper implements RankingConfig { public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler, ZenModeHelper zenHelper, NotificationChannelLogger notificationChannelLogger, - AppOpsManager appOpsManager) { + AppOpsManager appOpsManager, + SysUiStatsEvent.BuilderFactory statsEventBuilderFactory) { mContext = context; mZenModeHelper = zenHelper; mRankingHandler = rankingHandler; mPm = pm; mNotificationChannelLogger = notificationChannelLogger; mAppOps = appOpsManager; + mStatsEventBuilderFactory = statsEventBuilderFactory; updateBadgingEnabled(); updateBubblesEnabled(); @@ -1898,7 +1901,7 @@ public class PreferencesHelper implements RankingConfig { if (i > NOTIFICATION_PREFERENCES_PULL_LIMIT) { break; } - StatsEvent.Builder event = StatsEvent.newBuilder() + SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES); final PackagePreferences r = mPackagePreferences.valueAt(i); event.writeInt(r.uid); @@ -1927,7 +1930,7 @@ public class PreferencesHelper implements RankingConfig { if (++totalChannelsPulled > NOTIFICATION_CHANNEL_PULL_LIMIT) { break; } - StatsEvent.Builder event = StatsEvent.newBuilder() + SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES); event.writeInt(r.uid); event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); @@ -1962,7 +1965,7 @@ public class PreferencesHelper implements RankingConfig { if (++totalGroupsPulled > NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT) { break; } - StatsEvent.Builder event = StatsEvent.newBuilder() + SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES); event.writeInt(r.uid); event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); diff --git a/services/core/java/com/android/server/notification/SysUiStatsEvent.java b/services/core/java/com/android/server/notification/SysUiStatsEvent.java new file mode 100644 index 000000000000..9bc2346d4e96 --- /dev/null +++ b/services/core/java/com/android/server/notification/SysUiStatsEvent.java @@ -0,0 +1,68 @@ +/* + * 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.server.notification; + +import android.util.StatsEvent; + +/** + * Wrapper for StatsEvent that enables unit testing. + */ +public class SysUiStatsEvent { + + static class Builder { + private final StatsEvent.Builder mBuilder; + + protected Builder(StatsEvent.Builder builder) { + mBuilder = builder; + } + + public StatsEvent build() { + return mBuilder.build(); + } + + public Builder setAtomId(int atomId) { + mBuilder.setAtomId(atomId); + return this; + } + + public Builder writeInt(int value) { + mBuilder.writeInt(value); + return this; + } + + public Builder addBooleanAnnotation(byte annotation, boolean value) { + mBuilder.addBooleanAnnotation(annotation, value); + return this; + } + + public Builder writeString(String value) { + mBuilder.writeString(value); + return this; + } + + public Builder writeBoolean(boolean value) { + mBuilder.writeBoolean(value); + return this; + } + } + + static class BuilderFactory { + Builder newBuilder() { + return new Builder(StatsEvent.newBuilder()); + } + } +} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index fd861b56b729..6bb10c79d382 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -13451,7 +13451,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { for (String packageName : packagesToChange) { final PackageSetting ps = mSettings.mPackages.get(packageName); - if (ps.getSuspended(userId)) { + if (ps != null && ps.getSuspended(userId)) { ps.removeSuspension(suspendingPackagePredicate, userId); if (!ps.getSuspended(userId)) { unsuspendedPackages.add(ps.name); @@ -13492,7 +13492,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { for (String packageName : packagesToChange) { final PackageSetting ps = mSettings.mPackages.get(packageName); - if (ps.getDistractionFlags(userId) != 0) { + if (ps != null && ps.getDistractionFlags(userId) != 0) { ps.setDistractionFlags(0, userId); changedPackages.add(ps.name); changedUids.add(UserHandle.getUid(userId, ps.getAppId())); @@ -18884,6 +18884,7 @@ public class PackageManagerService extends IPackageManager.Stub int userId) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DELETE_PACKAGES, null); + // TODO (b/157774108): This should fail on non-existent packages. synchronized (mLock) { // Cannot block uninstall of static shared libs as they are // considered a part of the using app (emulating static linking). diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index b0e3ecb6d17b..d5c9424528bd 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -491,6 +491,7 @@ public class UserManagerService extends IUserManager.Stub { final SparseIntArray states; public WatchedUserStates() { states = new SparseIntArray(); + invalidateIsUserUnlockedCache(); } public int get(int userId) { return states.get(userId); diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 22455ad39960..6c1ff728e6b9 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -19,6 +19,8 @@ package com.android.server.stats.pull; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; +import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE; +import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -243,11 +245,6 @@ public class StatsPullAtomService extends SystemService { private static final String DANGEROUS_PERMISSION_STATE_SAMPLE_RATE = "dangerous_permission_state_sample_rate"; - private final Object mNetworkStatsLock = new Object(); - @GuardedBy("mNetworkStatsLock") - @Nullable - private INetworkStatsSession mNetworkStatsSession; - private final Object mThermalLock = new Object(); @GuardedBy("mThermalLock") private IThermalService mThermalService; @@ -325,7 +322,7 @@ public class StatsPullAtomService extends SystemService { // Listener for monitoring subscriptions changed event. private StatsSubscriptionsListener mStatsSubscriptionsListener; - // List that store SubInfo of subscriptions that ever appeared since boot. + // List that stores SubInfo of subscriptions that ever appeared since boot. private final CopyOnWriteArrayList<SubInfo> mHistoricalSubs = new CopyOnWriteArrayList<>(); public StatsPullAtomService(Context context) { @@ -681,7 +678,7 @@ public class StatsPullAtomService extends SystemService { collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER)); // Listen to subscription changes to record historical subscriptions that activated before - // pulling, this is used by {@link #pullMobileBytesTransfer}. + // pulling, this is used by {@code DATA_USAGE_BYTES_TRANSFER}. mSubscriptionManager.addOnSubscriptionsChangedListener( BackgroundThread.getExecutor(), mStatsSubscriptionsListener); @@ -696,32 +693,26 @@ public class StatsPullAtomService extends SystemService { /** * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or - * null if the service or binder cannot be obtained. + * null if the service or binder cannot be obtained. Calling this method will trigger poll + * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit} + * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where + * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at + * the network usage of their app. */ @Nullable - private INetworkStatsSession getNetworkStatsSession() { - synchronized (mNetworkStatsLock) { - if (mNetworkStatsSession != null) return mNetworkStatsSession; - - final INetworkStatsService networkStatsService = - INetworkStatsService.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); - if (networkStatsService == null) return null; + private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) { + final INetworkStatsService networkStatsService = + INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + if (networkStatsService == null) return null; - try { - networkStatsService.asBinder().linkToDeath(() -> { - synchronized (mNetworkStatsLock) { - mNetworkStatsSession = null; - } - }, /* flags */ 0); - mNetworkStatsSession = networkStatsService.openSessionForUsageStats( - FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, mContext.getOpPackageName()); - } catch (RemoteException e) { - Slog.e(TAG, "Cannot get NetworkStats session", e); - mNetworkStatsSession = null; - } - - return mNetworkStatsSession; + try { + return networkStatsService.openSessionForUsageStats( + FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE + : FLAG_POLL_ON_OPEN), mContext.getOpPackageName()); + } catch (RemoteException e) { + Slog.e(TAG, "Cannot get NetworkStats session", e); + return null; } } @@ -1032,7 +1023,13 @@ public class StatsPullAtomService extends SystemService { final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(), NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS); try { - final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template, + // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats + // history when query in every second in order to show realtime statistics. However, + // this is not a good long-term solution since NetworkStatsService will make frequent + // I/O and also block main thread when polling. + // Consider making perfd queries NetworkStatsService directly. + final NetworkStats stats = getNetworkStatsSession(template.getMatchRule() + == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis, includeTags); return stats; diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java index e675f4e8a46c..1c96a2e8c5c2 100644 --- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java +++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java @@ -74,7 +74,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Queue; -import java.util.stream.Collectors; /** * A manager for TextClassifier services. @@ -883,6 +882,9 @@ public final class TextClassificationManagerService extends ITextClassifierServi Slog.d(LOG_TAG, "Binding to " + serviceIntent.getComponent()); willBind = mContext.bindServiceAsUser( serviceIntent, mConnection, mBindServiceFlags, UserHandle.of(mUserId)); + if (!willBind) { + Slog.e(LOG_TAG, "Could not bind to " + componentName); + } mBinding = willBind; } finally { Binder.restoreCallingIdentity(identity); @@ -955,16 +957,19 @@ public final class TextClassificationManagerService extends ITextClassifierServi @Override public void onServiceDisconnected(ComponentName name) { + Slog.i(LOG_TAG, "onServiceDisconnected called with " + name); cleanupService(); } @Override public void onBindingDied(ComponentName name) { + Slog.i(LOG_TAG, "onBindingDied called with " + name); cleanupService(); } @Override public void onNullBinding(ComponentName name) { + Slog.i(LOG_TAG, "onNullBinding called with " + name); cleanupService(); } @@ -1047,18 +1052,26 @@ public final class TextClassificationManagerService extends ITextClassifierServi private static void rewriteTextClassificationIcons(Bundle result) { final TextClassification classification = TextClassifierService.getResponse(result); boolean rewrite = false; - for (RemoteAction action : classification.getActions()) { - rewrite |= shouldRewriteIcon(action); + final List<RemoteAction> actions = classification.getActions(); + final int size = actions.size(); + final List<RemoteAction> validActions = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + final RemoteAction action = actions.get(i); + final RemoteAction validAction; + if (shouldRewriteIcon(action)) { + rewrite = true; + validAction = validAction(action); + } else { + validAction = action; + } + validActions.add(validAction); } if (rewrite) { TextClassifierService.putResponse( result, classification.toBuilder() .clearActions() - .addActions(classification.getActions() - .stream() - .map(action -> validAction(action)) - .collect(Collectors.toList())) + .addActions(validActions) .build()); } } @@ -1066,29 +1079,30 @@ public final class TextClassificationManagerService extends ITextClassifierServi private static void rewriteConversationActionsIcons(Bundle result) { final ConversationActions convActions = TextClassifierService.getResponse(result); boolean rewrite = false; - for (ConversationAction convAction : convActions.getConversationActions()) { - rewrite |= shouldRewriteIcon(convAction.getAction()); + final List<ConversationAction> origConvActions = convActions.getConversationActions(); + final int size = origConvActions.size(); + final List<ConversationAction> validConvActions = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + final ConversationAction convAction = origConvActions.get(i); + final ConversationAction validConvAction; + if (shouldRewriteIcon(convAction.getAction())) { + rewrite = true; + validConvAction = convAction.toBuilder() + .setAction(validAction(convAction.getAction())) + .build(); + } else { + validConvAction = convAction; + } + validConvActions.add(validConvAction); } if (rewrite) { TextClassifierService.putResponse( result, - new ConversationActions( - convActions.getConversationActions() - .stream() - .map(convAction -> convAction.toBuilder() - .setAction(validAction(convAction.getAction())) - .build()) - .collect(Collectors.toList()), - convActions.getId())); + new ConversationActions(validConvActions, convActions.getId())); } } - @Nullable - private static RemoteAction validAction(@Nullable RemoteAction action) { - if (!shouldRewriteIcon(action)) { - return action; - } - + private static RemoteAction validAction(RemoteAction action) { final RemoteAction newAction = new RemoteAction( changeIcon(action.getIcon()), action.getTitle(), diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 3796c5fda411..9476e9260c73 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -114,7 +114,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed private static final int MAX_PERSISTED_URI_GRANTS = 128; - private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true; + private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); private final H mH; diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 7c33c7cf6398..fe2b144bcdd6 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1001,6 +1001,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (info.minAspectRatio != 0) { pw.println(prefix + "minAspectRatio=" + info.minAspectRatio); } + if (info.supportsSizeChanges) { + pw.println(prefix + "supportsSizeChanges=true"); + } } } @@ -6376,6 +6379,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * aspect ratio. */ boolean shouldUseSizeCompatMode() { + if (info.supportsSizeChanges) { + return false; + } if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) { final ActivityRecord root = task != null ? task.getRootActivity() : null; if (root != null && root != this && !root.shouldUseSizeCompatMode()) { diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 00b2a58dbe8f..7f03778ab1c7 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -819,6 +819,22 @@ class ActivityStack extends Task { mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); mRootWindowContainer.resumeFocusedStacksTopActivities(); + + final boolean pinnedToFullscreen = currentMode == WINDOWING_MODE_PINNED + && windowingMode == WINDOWING_MODE_FULLSCREEN; + if (pinnedToFullscreen && topActivity != null && !isForceHidden()) { + mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(true); + try { + // Report orientation as soon as possible so that the display can freeze earlier if + // the display orientation will be changed. Because the surface bounds of activity + // may have been set to fullscreen but the activity hasn't redrawn its content yet, + // the rotation animation needs to capture snapshot earlier to avoid animating from + // an intermediate state. + topActivity.reportDescendantOrientationChangeIfNeeded(); + } finally { + mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(false); + } + } } @Override diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8903776469db..59181a64f423 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1481,6 +1481,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // has it own policy for bounds, the activity bounds based on parent is unknown. return false; } + if (mPinnedStackControllerLocked.isPipActiveOrWindowingModeChanging()) { + // Use normal rotation animation because seamless PiP rotation is not supported yet. + return false; + } setFixedRotationLaunchingApp(r, rotation); return true; diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 56312aa1b0b8..52ada472f0aa 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -23,7 +23,6 @@ import android.app.RemoteAction; import android.content.ComponentName; import android.content.pm.ParceledListSlice; import android.content.res.Resources; -import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.util.DisplayMetrics; @@ -33,8 +32,6 @@ import android.view.DisplayInfo; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; -import com.android.server.UiThread; - import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -61,7 +58,6 @@ class PinnedStackController { private final WindowManagerService mService; private final DisplayContent mDisplayContent; - private final Handler mHandler = UiThread.getHandler(); private IPinnedStackListener mPinnedStackListener; private final PinnedStackListenerDeathHandler mPinnedStackListenerDeathHandler = @@ -69,6 +65,9 @@ class PinnedStackController { private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback(); + /** Whether the PiP is entering or leaving. */ + private boolean mIsPipWindowingModeChanging; + private boolean mIsImeShowing; private int mImeHeight; @@ -161,6 +160,20 @@ class PinnedStackController { Float.compare(aspectRatio, mMaxAspectRatio) <= 0; } + /** Returns {@code true} if the PiP is on screen or is changing windowing mode. */ + boolean isPipActiveOrWindowingModeChanging() { + if (mIsPipWindowingModeChanging) { + return true; + } + final Task pinnedTask = mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask(); + return pinnedTask != null && pinnedTask.hasChild(); + } + + /** Sets whether a visible stack is changing from or to pinned mode. */ + void setPipWindowingModeChanging(boolean isPipWindowingModeChanging) { + mIsPipWindowingModeChanging = isPipWindowingModeChanging; + } + /** * Activity is hidden (either stopped or removed), resets the last saved snap fraction * so that the default bounds will be returned for the next session. diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 0143eb1abe03..1b77fd2e8782 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -388,18 +388,15 @@ class SurfaceAnimator { final SurfaceControl.Builder builder = animatable.makeAnimationLeash() .setParent(animatable.getAnimationLeashParent()) .setName(surface + " - animation-leash") - .setColorLayer(); + // TODO(b/151665759) Defer reparent calls + // We want the leash to be visible immediately because the transaction which shows + // the leash may be deferred but the reparent will not. This will cause the leashed + // surface to be invisible until the deferred transaction is applied. If this + // doesn't work, you will can see the 2/3 button nav bar flicker during seamless + // rotation. + .setHidden(hidden) + .setEffectLayer(); final SurfaceControl leash = builder.build(); - if (!hidden) { - // TODO(b/151665759) Defer reparent calls - // We want the leash to be visible immediately but we want to set the effects on - // the layer. Since the transaction used in this function may be deferred, we apply - // another transaction immediately with the correct visibility and effects. - // If this doesn't work, you will can see the 2/3 button nav bar flicker during - // seamless rotation. - transactionFactory.get().unsetColor(leash).show(leash).apply(); - } - t.unsetColor(leash); t.setWindowCrop(leash, width, height); t.setPosition(leash, x, y); t.show(leash); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 345928e17768..039c0ee11968 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3203,14 +3203,8 @@ class Task extends WindowContainer<WindowContainer> { } @Override - void onSurfaceShown(SurfaceControl.Transaction t) { - super.onSurfaceShown(t); - t.unsetColor(mSurfaceControl); - } - - @Override void setInitialSurfaceControlProperties(SurfaceControl.Builder b) { - b.setColorLayer().setMetadata(METADATA_TASK_ID, mTaskId); + b.setEffectLayer().setMetadata(METADATA_TASK_ID, mTaskId); super.setInitialSurfaceControlProperties(b); } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 46680662c030..90156fd4f475 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1165,15 +1165,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } mOrientation = orientation; - final int configOrientation = getRequestedConfigurationOrientation(); - if (getRequestedOverrideConfiguration().orientation != configOrientation) { - mTmpConfig.setTo(getRequestedOverrideConfiguration()); - mTmpConfig.orientation = configOrientation; - onRequestedOverrideConfigurationChanged(mTmpConfig); - } - final WindowContainer parent = getParent(); if (parent != null) { + if (getConfiguration().orientation != getRequestedConfigurationOrientation()) { + // Resolve the requested orientation. + onConfigurationChanged(parent.getConfiguration()); + } onDescendantOrientationChanged(freezeDisplayToken, requestingContainer); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 46d6009b9ab8..045089082fd8 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -21,6 +21,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.OP_NONE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.isSplitScreenWindowingMode; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.os.PowerManager.DRAW_WAKE_LOCK; @@ -3757,6 +3758,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) { return false; } + // TODO(157912944): formalize drag-resizing so that exceptions aren't hardcoded like this + if (task.getActivityType() == ACTIVITY_TYPE_HOME) { + // The current sys-ui implementations never live-resize home, so to prevent WSA from + // creating/destroying surfaces (which messes up sync-transactions), skip HOME tasks. + return false; + } if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) { // Floating windows never enter drag resize mode. return false; diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index 2fcb005e6df8..885f4d2d34d7 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -268,22 +268,14 @@ IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_v mAppOpsManager(sm.getAppOpsManager()), mJni(sm.getJni()), mLooper(sm.getLooper()), + mTimedQueue(sm.getTimedQueue()), mIncrementalDir(rootDir) { - if (!mVold) { - LOG(FATAL) << "Vold service is unavailable"; - } - if (!mDataLoaderManager) { - LOG(FATAL) << "DataLoaderManagerService is unavailable"; - } - if (!mAppOpsManager) { - LOG(FATAL) << "AppOpsManager is unavailable"; - } - if (!mJni) { - LOG(FATAL) << "JNI is unavailable"; - } - if (!mLooper) { - LOG(FATAL) << "Looper is unavailable"; - } + CHECK(mVold) << "Vold service is unavailable"; + CHECK(mDataLoaderManager) << "DataLoaderManagerService is unavailable"; + CHECK(mAppOpsManager) << "AppOpsManager is unavailable"; + CHECK(mJni) << "JNI is unavailable"; + CHECK(mLooper) << "Looper is unavailable"; + CHECK(mTimedQueue) << "TimedQueue is unavailable"; mJobQueue.reserve(16); mJobProcessor = std::thread([this]() { @@ -294,10 +286,6 @@ IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_v mJni->initializeForCurrentThread(); runCmdLooper(); }); - mTimerThread = std::thread([this]() { - mJni->initializeForCurrentThread(); - runTimers(); - }); const auto mountedRootNames = adoptMountedInstances(); mountExistingImages(mountedRootNames); @@ -310,10 +298,8 @@ IncrementalService::~IncrementalService() { } mJobCondition.notify_all(); mJobProcessor.join(); - mTimerCondition.notify_all(); - mTimerThread.join(); mCmdLooperThread.join(); - mTimedJobs.clear(); + mTimedQueue->stop(); // Ensure that mounts are destroyed while the service is still valid. mBindsByPath.clear(); mMounts.clear(); @@ -1710,53 +1696,18 @@ void IncrementalService::onAppOpChanged(const std::string& packageName) { } } -void IncrementalService::addTimedJob(MountId id, TimePoint when, Job what) { +void IncrementalService::addTimedJob(MountId id, Milliseconds after, Job what) { if (id == kInvalidStorageId) { return; } - { - std::unique_lock lock(mTimerMutex); - mTimedJobs.insert(TimedJob{id, when, std::move(what)}); - } - mTimerCondition.notify_all(); + mTimedQueue->addJob(id, after, std::move(what)); } void IncrementalService::removeTimedJobs(MountId id) { if (id == kInvalidStorageId) { return; } - { - std::unique_lock lock(mTimerMutex); - std::erase_if(mTimedJobs, [id](auto&& item) { return item.id == id; }); - } -} - -void IncrementalService::runTimers() { - static constexpr TimePoint kInfinityTs{Clock::duration::max()}; - TimePoint nextTaskTs = kInfinityTs; - for (;;) { - std::unique_lock lock(mTimerMutex); - mTimerCondition.wait_until(lock, nextTaskTs, [this]() { - auto now = Clock::now(); - return !mRunning || (!mTimedJobs.empty() && mTimedJobs.begin()->when <= now); - }); - if (!mRunning) { - return; - } - - auto now = Clock::now(); - auto it = mTimedJobs.begin(); - // Always acquire begin(). We can't use it after unlock as mTimedJobs can change. - for (; it != mTimedJobs.end() && it->when <= now; it = mTimedJobs.begin()) { - auto job = it->what; - mTimedJobs.erase(it); - - lock.unlock(); - job(); - lock.lock(); - } - nextTaskTs = it != mTimedJobs.end() ? it->when : kInfinityTs; - } + mTimedQueue->removeJobs(id); } IncrementalService::DataLoaderStub::DataLoaderStub(IncrementalService& service, MountId id, @@ -2029,8 +1980,8 @@ void IncrementalService::DataLoaderStub::updateHealthStatus(bool baseline) { mHealthBase = {now, kernelTsUs}; } - if (kernelTsUs == kMaxBootClockTsUs || mHealthBase.userTs > now || - mHealthBase.kernelTsUs > kernelTsUs) { + if (kernelTsUs == kMaxBootClockTsUs || mHealthBase.kernelTsUs == kMaxBootClockTsUs || + mHealthBase.userTs > now) { LOG(DEBUG) << id() << ": No pending reads or invalid base, report Ok and wait."; registerForPendingReads(); healthStatusToReport = IStorageHealthListener::HEALTH_STATUS_OK; @@ -2056,6 +2007,9 @@ void IncrementalService::DataLoaderStub::updateHealthStatus(bool baseline) { return; } + // Don't schedule timer job less than 500ms in advance. + static constexpr auto kTolerance = 500ms; + const auto blockedTimeout = std::chrono::milliseconds(mHealthCheckParams.blockedTimeoutMs); const auto unhealthyTimeout = std::chrono::milliseconds(mHealthCheckParams.unhealthyTimeoutMs); @@ -2065,31 +2019,28 @@ void IncrementalService::DataLoaderStub::updateHealthStatus(bool baseline) { const auto kernelDeltaUs = kernelTsUs - mHealthBase.kernelTsUs; const auto userTs = mHealthBase.userTs + std::chrono::microseconds(kernelDeltaUs); - const auto delta = now - userTs; + const auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(now - userTs); - TimePoint whenToCheckBack; - if (delta < blockedTimeout) { + Milliseconds checkBackAfter; + if (delta + kTolerance < blockedTimeout) { LOG(DEBUG) << id() << ": Report reads pending and wait for blocked status."; - whenToCheckBack = userTs + blockedTimeout; + checkBackAfter = blockedTimeout - delta; healthStatusToReport = IStorageHealthListener::HEALTH_STATUS_READS_PENDING; - } else if (delta < unhealthyTimeout) { + } else if (delta + kTolerance < unhealthyTimeout) { LOG(DEBUG) << id() << ": Report blocked and wait for unhealthy."; - whenToCheckBack = userTs + unhealthyTimeout; + checkBackAfter = unhealthyTimeout - delta; healthStatusToReport = IStorageHealthListener::HEALTH_STATUS_BLOCKED; } else { LOG(DEBUG) << id() << ": Report unhealthy and continue monitoring."; - whenToCheckBack = now + unhealthyMonitoring; + checkBackAfter = unhealthyMonitoring; healthStatusToReport = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY; } - LOG(DEBUG) << id() << ": updateHealthStatus in " - << double(std::chrono::duration_cast<std::chrono::milliseconds>(whenToCheckBack - - now) - .count()) / - 1000.0 + LOG(DEBUG) << id() << ": updateHealthStatus in " << double(checkBackAfter.count()) / 1000.0 << "secs"; - mService.addTimedJob(id(), whenToCheckBack, [this]() { updateHealthStatus(); }); + mService.addTimedJob(id(), checkBackAfter, [this]() { updateHealthStatus(); }); } + // With kTolerance we are expecting these to execute before the next update. if (healthStatusToReport != -1) { onHealthStatus(healthListener, healthStatusToReport); } @@ -2178,6 +2129,16 @@ void IncrementalService::DataLoaderStub::onDump(int fd) { dprintf(fd, " targetStatus: %d\n", mTargetStatus); dprintf(fd, " targetStatusTs: %lldmcs\n", (long long)(elapsedMcs(mTargetStatusTs, Clock::now()))); + dprintf(fd, " health: {\n"); + dprintf(fd, " path: %s\n", mHealthPath.c_str()); + dprintf(fd, " base: %lldmcs (%lld)\n", + (long long)(elapsedMcs(mHealthBase.userTs, Clock::now())), + (long long)mHealthBase.kernelTsUs); + dprintf(fd, " blockedTimeoutMs: %d\n", int(mHealthCheckParams.blockedTimeoutMs)); + dprintf(fd, " unhealthyTimeoutMs: %d\n", int(mHealthCheckParams.unhealthyTimeoutMs)); + dprintf(fd, " unhealthyMonitoringMs: %d\n", + int(mHealthCheckParams.unhealthyMonitoringMs)); + dprintf(fd, " }\n"); const auto& params = mParams; dprintf(fd, " dataLoaderParams: {\n"); dprintf(fd, " type: %s\n", toString(params.type).c_str()); diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h index 57e4669d53de..918531b7921c 100644 --- a/services/incremental/IncrementalService.h +++ b/services/incremental/IncrementalService.h @@ -56,8 +56,6 @@ using StorageId = int; using FileId = incfs::FileId; using BlockIndex = incfs::BlockIndex; using RawMetadata = incfs::RawMetadata; -using Clock = std::chrono::steady_clock; -using TimePoint = std::chrono::time_point<Clock>; using Seconds = std::chrono::seconds; using BootClockTsUs = uint64_t; @@ -338,8 +336,6 @@ private: bool unregisterAppOpsCallback(const std::string& packageName); void onAppOpChanged(const std::string& packageName); - using Job = std::function<void()>; - void runJobProcessing(); void extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile, ZipEntry& entry, const incfs::FileId& libFileId, std::string_view targetLibPath, @@ -347,9 +343,8 @@ private: void runCmdLooper(); - void addTimedJob(MountId id, TimePoint when, Job what); + void addTimedJob(MountId id, Milliseconds after, Job what); void removeTimedJobs(MountId id); - void runTimers(); private: const std::unique_ptr<VoldServiceWrapper> mVold; @@ -358,6 +353,7 @@ private: const std::unique_ptr<AppOpsManagerWrapper> mAppOpsManager; const std::unique_ptr<JniWrapper> mJni; const std::unique_ptr<LooperWrapper> mLooper; + const std::unique_ptr<TimedQueueWrapper> mTimedQueue; const std::string mIncrementalDir; mutable std::mutex mLock; @@ -380,19 +376,6 @@ private: std::thread mJobProcessor; std::thread mCmdLooperThread; - - struct TimedJob { - MountId id; - TimePoint when; - Job what; - friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) { - return lhs.when < rhs.when; - } - }; - std::set<TimedJob> mTimedJobs; - std::condition_variable mTimerCondition; - std::mutex mTimerMutex; - std::thread mTimerThread; }; } // namespace android::incremental diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp index a76aa625ebc6..99a35adb5074 100644 --- a/services/incremental/ServiceWrappers.cpp +++ b/services/incremental/ServiceWrappers.cpp @@ -25,6 +25,8 @@ #include <binder/AppOpsManager.h> #include <utils/String16.h> +#include <thread> + #include "IncrementalServiceValidation.h" using namespace std::literals; @@ -181,6 +183,88 @@ public: } }; +static JNIEnv* getOrAttachJniEnv(JavaVM* jvm); + +class RealTimedQueueWrapper : public TimedQueueWrapper { +public: + RealTimedQueueWrapper(JavaVM* jvm) { + mThread = std::thread([this, jvm]() { + (void)getOrAttachJniEnv(jvm); + runTimers(); + }); + } + ~RealTimedQueueWrapper() final { + CHECK(!mRunning) << "call stop first"; + CHECK(!mThread.joinable()) << "call stop first"; + } + + void addJob(MountId id, Milliseconds after, Job what) final { + const auto now = Clock::now(); + { + std::unique_lock lock(mMutex); + mJobs.insert(TimedJob{id, now + after, std::move(what)}); + } + mCondition.notify_all(); + } + void removeJobs(MountId id) final { + std::unique_lock lock(mMutex); + std::erase_if(mJobs, [id](auto&& item) { return item.id == id; }); + } + void stop() final { + { + std::unique_lock lock(mMutex); + mRunning = false; + } + mCondition.notify_all(); + mThread.join(); + mJobs.clear(); + } + +private: + void runTimers() { + static constexpr TimePoint kInfinityTs{Clock::duration::max()}; + TimePoint nextJobTs = kInfinityTs; + std::unique_lock lock(mMutex); + for (;;) { + mCondition.wait_until(lock, nextJobTs, [this, nextJobTs]() { + const auto now = Clock::now(); + const auto firstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs; + return !mRunning || firstJobTs <= now || firstJobTs < nextJobTs; + }); + if (!mRunning) { + return; + } + + const auto now = Clock::now(); + auto it = mJobs.begin(); + // Always acquire begin(). We can't use it after unlock as mTimedJobs can change. + for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) { + auto job = std::move(it->what); + mJobs.erase(it); + + lock.unlock(); + job(); + lock.lock(); + } + nextJobTs = it != mJobs.end() ? it->when : kInfinityTs; + } + } + + struct TimedJob { + MountId id; + TimePoint when; + Job what; + friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) { + return lhs.when < rhs.when; + } + }; + bool mRunning = true; + std::set<TimedJob> mJobs; + std::condition_variable mCondition; + std::mutex mMutex; + std::thread mThread; +}; + RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env) : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {} @@ -228,6 +312,10 @@ std::unique_ptr<LooperWrapper> RealServiceManager::getLooper() { return std::make_unique<RealLooperWrapper>(); } +std::unique_ptr<TimedQueueWrapper> RealServiceManager::getTimedQueue() { + return std::make_unique<RealTimedQueueWrapper>(mJvm); +} + static JavaVM* getJavaVm(JNIEnv* env) { CHECK(env); JavaVM* jvm = nullptr; diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h index a935ab99267e..8cd726fdc0f1 100644 --- a/services/incremental/ServiceWrappers.h +++ b/services/incremental/ServiceWrappers.h @@ -35,6 +35,11 @@ namespace android::incremental { +using Clock = std::chrono::steady_clock; +using TimePoint = std::chrono::time_point<Clock>; +using Milliseconds = std::chrono::milliseconds; +using Job = std::function<void()>; + // --- Wrapper interfaces --- using MountId = int32_t; @@ -121,6 +126,14 @@ public: virtual int pollAll(int timeoutMillis) = 0; }; +class TimedQueueWrapper { +public: + virtual ~TimedQueueWrapper() = default; + virtual void addJob(MountId id, Milliseconds after, Job what) = 0; + virtual void removeJobs(MountId id) = 0; + virtual void stop() = 0; +}; + class ServiceManagerWrapper { public: virtual ~ServiceManagerWrapper() = default; @@ -130,6 +143,7 @@ public: virtual std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() = 0; virtual std::unique_ptr<JniWrapper> getJni() = 0; virtual std::unique_ptr<LooperWrapper> getLooper() = 0; + virtual std::unique_ptr<TimedQueueWrapper> getTimedQueue() = 0; }; // --- Real stuff --- @@ -144,6 +158,7 @@ public: std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final; std::unique_ptr<JniWrapper> getJni() final; std::unique_ptr<LooperWrapper> getLooper() final; + std::unique_ptr<TimedQueueWrapper> getTimedQueue() final; private: template <class INTERFACE> diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp index 84ec7d3b2c24..26b5094a795a 100644 --- a/services/incremental/test/IncrementalServiceTest.cpp +++ b/services/incremental/test/IncrementalServiceTest.cpp @@ -22,6 +22,7 @@ #include <gtest/gtest.h> #include <utils/Log.h> +#include <chrono> #include <future> #include "IncrementalService.h" @@ -295,9 +296,21 @@ public: void openMountSuccess() { ON_CALL(*this, openMount(_)).WillByDefault(Invoke(this, &MockIncFs::openMountForHealth)); } - void waitForPendingReadsSuccess() { + + // 1000ms + void waitForPendingReadsSuccess(uint64_t ts = 0) { + ON_CALL(*this, waitForPendingReads(_, _, _)) + .WillByDefault( + Invoke([ts](const Control& control, std::chrono::milliseconds timeout, + std::vector<incfs::ReadInfo>* pendingReadsBuffer) { + pendingReadsBuffer->push_back({.bootClockTsUs = ts}); + return android::incfs::WaitResult::HaveData; + })); + } + + void waitForPendingReadsTimeout() { ON_CALL(*this, waitForPendingReads(_, _, _)) - .WillByDefault(Invoke(this, &MockIncFs::waitForPendingReadsForHealth)); + .WillByDefault(Return(android::incfs::WaitResult::Timeout)); } static constexpr auto kPendingReadsFd = 42; @@ -305,13 +318,6 @@ public: return UniqueControl(IncFs_CreateControl(-1, kPendingReadsFd, -1)); } - WaitResult waitForPendingReadsForHealth( - const Control& control, std::chrono::milliseconds timeout, - std::vector<incfs::ReadInfo>* pendingReadsBuffer) const { - pendingReadsBuffer->push_back({.bootClockTsUs = 0}); - return android::incfs::WaitResult::HaveData; - } - RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) { metadata::Mount m; m.mutable_storage()->set_id(100); @@ -371,7 +377,7 @@ class MockJniWrapper : public JniWrapper { public: MOCK_CONST_METHOD0(initializeForCurrentThread, void()); - MockJniWrapper() { EXPECT_CALL(*this, initializeForCurrentThread()).Times(3); } + MockJniWrapper() { EXPECT_CALL(*this, initializeForCurrentThread()).Times(2); } }; class MockLooperWrapper : public LooperWrapper { @@ -385,7 +391,7 @@ public: ON_CALL(*this, addFd(_, _, _, _, _)) .WillByDefault(Invoke(this, &MockLooperWrapper::storeCallback)); ON_CALL(*this, removeFd(_)).WillByDefault(Invoke(this, &MockLooperWrapper::clearCallback)); - ON_CALL(*this, pollAll(_)).WillByDefault(Invoke(this, &MockLooperWrapper::sleepFor)); + ON_CALL(*this, pollAll(_)).WillByDefault(Invoke(this, &MockLooperWrapper::wait10Ms)); } int storeCallback(int, int, int, android::Looper_callbackFunc callback, void* data) { @@ -400,8 +406,10 @@ public: return 0; } - int sleepFor(int timeoutMillis) { - std::this_thread::sleep_for(std::chrono::milliseconds(timeoutMillis)); + int wait10Ms(int) { + // This is called from a loop in runCmdLooper. + // Sleeping for 10ms only to avoid busy looping. + std::this_thread::sleep_for(10ms); return 0; } @@ -409,6 +417,55 @@ public: void* mCallbackData = nullptr; }; +class MockTimedQueueWrapper : public TimedQueueWrapper { +public: + MOCK_METHOD3(addJob, void(MountId, Milliseconds, Job)); + MOCK_METHOD1(removeJobs, void(MountId)); + MOCK_METHOD0(stop, void()); + + MockTimedQueueWrapper() { + ON_CALL(*this, addJob(_, _, _)) + .WillByDefault(Invoke(this, &MockTimedQueueWrapper::storeJob)); + ON_CALL(*this, removeJobs(_)).WillByDefault(Invoke(this, &MockTimedQueueWrapper::clearJob)); + } + + void storeJob(MountId id, Milliseconds after, Job what) { + mId = id; + mAfter = after; + mWhat = std::move(what); + } + + void clearJob(MountId id) { + if (mId == id) { + mAfter = {}; + mWhat = {}; + } + } + + MountId mId = -1; + Milliseconds mAfter; + Job mWhat; +}; + +class MockStorageHealthListener : public os::incremental::BnStorageHealthListener { +public: + MOCK_METHOD2(onHealthStatus, binder::Status(int32_t storageId, int32_t status)); + + MockStorageHealthListener() { + ON_CALL(*this, onHealthStatus(_, _)) + .WillByDefault(Invoke(this, &MockStorageHealthListener::storeStorageIdAndStatus)); + } + + binder::Status storeStorageIdAndStatus(int32_t storageId, int32_t status) { + mStorageId = storageId; + mStatus = status; + return binder::Status::ok(); + } + + int32_t mStorageId = -1; + int32_t mStatus = -1; +}; + class MockServiceManager : public ServiceManagerWrapper { public: MockServiceManager(std::unique_ptr<MockVoldService> vold, @@ -416,13 +473,15 @@ public: std::unique_ptr<MockIncFs> incfs, std::unique_ptr<MockAppOpsManager> appOpsManager, std::unique_ptr<MockJniWrapper> jni, - std::unique_ptr<MockLooperWrapper> looper) + std::unique_ptr<MockLooperWrapper> looper, + std::unique_ptr<MockTimedQueueWrapper> timedQueue) : mVold(std::move(vold)), mDataLoaderManager(std::move(dataLoaderManager)), mIncFs(std::move(incfs)), mAppOpsManager(std::move(appOpsManager)), mJni(std::move(jni)), - mLooper(std::move(looper)) {} + mLooper(std::move(looper)), + mTimedQueue(std::move(timedQueue)) {} std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); } std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final { return std::move(mDataLoaderManager); @@ -431,6 +490,7 @@ public: std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final { return std::move(mAppOpsManager); } std::unique_ptr<JniWrapper> getJni() final { return std::move(mJni); } std::unique_ptr<LooperWrapper> getLooper() final { return std::move(mLooper); } + std::unique_ptr<TimedQueueWrapper> getTimedQueue() final { return std::move(mTimedQueue); } private: std::unique_ptr<MockVoldService> mVold; @@ -439,6 +499,7 @@ private: std::unique_ptr<MockAppOpsManager> mAppOpsManager; std::unique_ptr<MockJniWrapper> mJni; std::unique_ptr<MockLooperWrapper> mLooper; + std::unique_ptr<MockTimedQueueWrapper> mTimedQueue; }; // --- IncrementalServiceTest --- @@ -460,6 +521,8 @@ public: mJni = jni.get(); auto looper = std::make_unique<NiceMock<MockLooperWrapper>>(); mLooper = looper.get(); + auto timedQueue = std::make_unique<NiceMock<MockTimedQueueWrapper>>(); + mTimedQueue = timedQueue.get(); mIncrementalService = std::make_unique<IncrementalService>(MockServiceManager(std::move(vold), std::move( @@ -467,7 +530,8 @@ public: std::move(incFs), std::move(appOps), std::move(jni), - std::move(looper)), + std::move(looper), + std::move(timedQueue)), mRootDir.path); mDataLoaderParcel.packageName = "com.test"; mDataLoaderParcel.arguments = "uri"; @@ -503,6 +567,7 @@ protected: NiceMock<MockAppOpsManager>* mAppOpsManager = nullptr; NiceMock<MockJniWrapper>* mJni = nullptr; NiceMock<MockLooperWrapper>* mLooper = nullptr; + NiceMock<MockTimedQueueWrapper>* mTimedQueue = nullptr; NiceMock<MockDataLoader>* mDataLoader = nullptr; std::unique_ptr<IncrementalService> mIncrementalService; TemporaryDir mRootDir; @@ -710,6 +775,136 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderRecreateOnPendingReads) { mLooper->mCallback(-1, -1, mLooper->mCallbackData); } +TEST_F(IncrementalServiceTest, testStartDataLoaderUnhealthyStorage) { + mVold->mountIncFsSuccess(); + mIncFs->makeFileSuccess(); + mIncFs->openMountSuccess(); + mVold->bindMountSuccess(); + mDataLoaderManager->bindToDataLoaderSuccess(); + mDataLoaderManager->getDataLoaderSuccess(); + EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1); + EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1); + EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1); + EXPECT_CALL(*mDataLoader, start(_)).Times(1); + EXPECT_CALL(*mDataLoader, destroy(_)).Times(1); + EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); + EXPECT_CALL(*mLooper, addFd(MockIncFs::kPendingReadsFd, _, _, _, _)).Times(2); + EXPECT_CALL(*mLooper, removeFd(MockIncFs::kPendingReadsFd)).Times(2); + EXPECT_CALL(*mTimedQueue, addJob(_, _, _)).Times(4); + + sp<NiceMock<MockStorageHealthListener>> listener{new NiceMock<MockStorageHealthListener>}; + NiceMock<MockStorageHealthListener>* listenerMock = listener.get(); + EXPECT_CALL(*listenerMock, onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_OK)) + .Times(2); + EXPECT_CALL(*listenerMock, + onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_READS_PENDING)) + .Times(1); + EXPECT_CALL(*listenerMock, onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_BLOCKED)) + .Times(1); + EXPECT_CALL(*listenerMock, onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_UNHEALTHY)) + .Times(2); + + StorageHealthCheckParams params; + params.blockedTimeoutMs = 10000; + params.unhealthyTimeoutMs = 20000; + params.unhealthyMonitoringMs = 30000; + + using MS = std::chrono::milliseconds; + using MCS = std::chrono::microseconds; + + const auto blockedTimeout = MS(params.blockedTimeoutMs); + const auto unhealthyTimeout = MS(params.unhealthyTimeoutMs); + const auto unhealthyMonitoring = MS(params.unhealthyMonitoringMs); + + const uint64_t kFirstTimestampUs = 1000000000ll; + const uint64_t kBlockedTimestampUs = + kFirstTimestampUs - std::chrono::duration_cast<MCS>(blockedTimeout).count(); + const uint64_t kUnhealthyTimestampUs = + kFirstTimestampUs - std::chrono::duration_cast<MCS>(unhealthyTimeout).count(); + + TemporaryDir tempDir; + int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), + IncrementalService::CreateOptions::CreateNew, + {}, std::move(params), listener); + ASSERT_GE(storageId, 0); + + // Healthy state, registered for pending reads. + ASSERT_NE(nullptr, mLooper->mCallback); + ASSERT_NE(nullptr, mLooper->mCallbackData); + ASSERT_EQ(storageId, listener->mStorageId); + ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_OK, listener->mStatus); + + // Looper/epoll callback. + mIncFs->waitForPendingReadsSuccess(kFirstTimestampUs); + mLooper->mCallback(-1, -1, mLooper->mCallbackData); + + // Unregister from pending reads and wait. + ASSERT_EQ(nullptr, mLooper->mCallback); + ASSERT_EQ(nullptr, mLooper->mCallbackData); + ASSERT_EQ(storageId, listener->mStorageId); + ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_READS_PENDING, listener->mStatus); + // Timed callback present. + ASSERT_EQ(storageId, mTimedQueue->mId); + ASSERT_GE(mTimedQueue->mAfter, blockedTimeout); + auto timedCallback = mTimedQueue->mWhat; + mTimedQueue->clearJob(storageId); + + // Timed job callback for blocked. + mIncFs->waitForPendingReadsSuccess(kBlockedTimestampUs); + timedCallback(); + + // Still not registered, and blocked. + ASSERT_EQ(nullptr, mLooper->mCallback); + ASSERT_EQ(nullptr, mLooper->mCallbackData); + ASSERT_EQ(storageId, listener->mStorageId); + ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_BLOCKED, listener->mStatus); + // Timed callback present. + ASSERT_EQ(storageId, mTimedQueue->mId); + ASSERT_GE(mTimedQueue->mAfter, 1000ms); + timedCallback = mTimedQueue->mWhat; + mTimedQueue->clearJob(storageId); + + // Timed job callback for unhealthy. + mIncFs->waitForPendingReadsSuccess(kUnhealthyTimestampUs); + timedCallback(); + + // Still not registered, and blocked. + ASSERT_EQ(nullptr, mLooper->mCallback); + ASSERT_EQ(nullptr, mLooper->mCallbackData); + ASSERT_EQ(storageId, listener->mStorageId); + ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_UNHEALTHY, listener->mStatus); + // Timed callback present. + ASSERT_EQ(storageId, mTimedQueue->mId); + ASSERT_GE(mTimedQueue->mAfter, unhealthyMonitoring); + timedCallback = mTimedQueue->mWhat; + mTimedQueue->clearJob(storageId); + + // One more unhealthy. + mIncFs->waitForPendingReadsSuccess(kUnhealthyTimestampUs); + timedCallback(); + + // Still not registered, and blocked. + ASSERT_EQ(nullptr, mLooper->mCallback); + ASSERT_EQ(nullptr, mLooper->mCallbackData); + ASSERT_EQ(storageId, listener->mStorageId); + ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_UNHEALTHY, listener->mStatus); + // Timed callback present. + ASSERT_EQ(storageId, mTimedQueue->mId); + ASSERT_GE(mTimedQueue->mAfter, unhealthyMonitoring); + timedCallback = mTimedQueue->mWhat; + mTimedQueue->clearJob(storageId); + + // And now healthy. + mIncFs->waitForPendingReadsTimeout(); + timedCallback(); + + // Healthy state, registered for pending reads. + ASSERT_NE(nullptr, mLooper->mCallback); + ASSERT_NE(nullptr, mLooper->mCallbackData); + ASSERT_EQ(storageId, listener->mStorageId); + ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_OK, listener->mStatus); +} + TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccess) { mVold->mountIncFsSuccess(); mIncFs->makeFileSuccess(); diff --git a/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java b/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java index d89bbe9dd14e..d008b72c6bad 100644 --- a/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java +++ b/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java @@ -148,6 +148,9 @@ class UsageStatsQueryHelper { UsageStatsManager.INTERVAL_BEST, startTime, endTime, /* obfuscateInstantApps= */ false); Map<String, AppUsageStatsData> aggregatedStats = new ArrayMap<>(); + if (stats == null) { + return aggregatedStats; + } for (UsageStats stat : stats) { String packageName = stat.getPackageName(); if (packageNameFilter.contains(packageName)) { diff --git a/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java index 30ff1196cec0..e9686071409e 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java @@ -18,6 +18,8 @@ package com.android.server.people.data; import static com.android.server.people.data.TestUtils.timestamp; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -235,6 +237,19 @@ public final class UsageStatsQueryHelperTest { assertEquals(5, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getLaunchCount()); } + @Test + public void testQueryAppUsageStats_nullUsageStats() { + when(mUsageStatsManagerInternal.queryUsageStatsForUser(anyInt(), anyInt(), anyLong(), + anyLong(), anyBoolean())).thenReturn(null); + + Map<String, AppUsageStatsData> appLaunchChooserCountCounts = + mHelper.queryAppUsageStats(USER_ID_PRIMARY, 90_000L, + 200_000L, + Set.of(PKG_NAME_1)); + + assertThat(appLaunchChooserCountCounts).isEmpty(); + } + private void addUsageEvents(UsageEvents.Event... events) { UsageEvents usageEvents = new UsageEvents(Arrays.asList(events), new String[]{}); when(mUsageStatsManagerInternal.queryEventsForUser(anyInt(), anyLong(), anyLong(), diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp index b7199f7cdd5a..4439f998a527 100644 --- a/services/tests/uiservicestests/Android.bp +++ b/services/tests/uiservicestests/Android.bp @@ -21,6 +21,7 @@ android_test { "mockito-target-inline-minus-junit4", "platform-test-annotations", "platformprotosnano", + "statsdprotolite", "hamcrest-library", "testables", "truth-prebuilt", diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java index 13457f0a284c..162b2c4ac2d0 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java @@ -431,7 +431,7 @@ public class BubbleExtractorTest extends UiServiceTestCase { } @Test - public void testFlagBubble_false_notConversation() { + public void testFlagBubble_false_noShortcut() { setUpBubblesEnabled(true /* feature */, BUBBLE_PREFERENCE_ALL /* app */, DEFAULT_ALLOW_BUBBLE /* channel */); @@ -439,7 +439,6 @@ public class BubbleExtractorTest extends UiServiceTestCase { setUpIntentBubble(true /* isValid */); NotificationRecord r = getNotificationRecord(true /* bubble */); - // No longer a conversation: r.setShortcutInfo(null); r.getNotification().extras.putString(Notification.EXTRA_TEMPLATE, null); @@ -451,6 +450,25 @@ public class BubbleExtractorTest extends UiServiceTestCase { } @Test + public void testFlagBubble_false_notConversation() { + setUpBubblesEnabled(true /* feature */, + BUBBLE_PREFERENCE_ALL /* app */, + DEFAULT_ALLOW_BUBBLE /* channel */); + when(mActivityManager.isLowRamDevice()).thenReturn(false); + setUpIntentBubble(true /* isValid */); + + NotificationRecord r = getNotificationRecord(true /* bubble */); + r.userDemotedAppFromConvoSpace(true); + r.getNotification().extras.putString(Notification.EXTRA_TEMPLATE, null); + + mBubbleExtractor.process(r); + + assertFalse(r.canBubble()); + assertNull(r.getNotification().getBubbleMetadata()); + assertFalse(r.getNotification().isBubbleNotification()); + } + + @Test public void testFlagBubble_false_lowRamDevice() { setUpBubblesEnabled(true /* feature */, BUBBLE_PREFERENCE_ALL /* app */, diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index cf636823d5f7..de9b77c68336 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -5309,6 +5309,28 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException { + setUpPrefsForBubbles(PKG, mUid, + true /* global */, + BUBBLE_PREFERENCE_ALL /* app */, + true /* channel */); + + Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false); + nb.setShortcutId(null); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + null, mUid, 0, + nb.build(), new UserHandle(mUid), null, 0); + + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + + // no shortcut no bubble + assertFalse(mService.getNotificationRecord( + sbn.getKey()).getNotification().isBubbleNotification()); + } + + @Test public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException { setUpPrefsForBubbles(PKG, mUid, true /* global */, diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 1d6f8233b7b4..622a203c5242 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -29,6 +29,16 @@ import static android.app.NotificationManager.IMPORTANCE_MAX; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; +import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID; +import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_ID_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_NAME_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IMPORTANCE_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_CONVERSATION_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DELETED_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DEMOTED_CONVERSATION_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_IMPORTANT_CONVERSATION_FIELD_NUMBER; +import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.UID_FIELD_NUMBER; import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE; import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT; import static com.android.server.notification.PreferencesHelper.UNKNOWN_UID; @@ -91,7 +101,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.FastXmlSerializer; import com.android.server.UiServiceTestCase; - import org.json.JSONArray; import org.json.JSONObject; import org.junit.Before; @@ -110,6 +119,7 @@ import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -146,6 +156,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { private PreferencesHelper mHelper; private AudioAttributes mAudioAttributes; private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake(); + private WrappedSysUiStatsEvent.WrappedBuilderFactory mStatsEventBuilderFactory; @Before public void setUp() throws Exception { @@ -197,8 +208,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString(), eq(null), anyString())).thenReturn(MODE_DEFAULT); + + mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory(); + mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); resetZenModeHelper(); mAudioAttributes = new AudioAttributes.Builder() @@ -1483,7 +1497,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); @@ -1495,7 +1509,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0); when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); resetZenModeHelper(); @@ -2262,7 +2276,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { + "</package>\n" + "</ranking>\n"; mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadByteArrayXml(preQXml.getBytes(), true, UserHandle.USER_SYSTEM); assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, @@ -2275,7 +2289,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, @@ -2372,7 +2386,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); @@ -2384,7 +2398,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); @@ -2397,7 +2411,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); @@ -2410,7 +2424,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); // appears disabled @@ -2429,7 +2443,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); // appears disabled @@ -2448,7 +2462,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O)); @@ -2503,7 +2517,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O)); @@ -2540,7 +2554,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE); @@ -3019,31 +3033,6 @@ public class PreferencesHelperTest extends UiServiceTestCase { PKG_O, UID_O, parent.getId(), conversationId, false, false), conversationId); } - - @Test - public void testPullConversationNotificationChannel() { - String conversationId = "friend"; - - NotificationChannel parent = - new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); - mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); - - String channelId = String.format( - CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); - NotificationChannel friend = new NotificationChannel(channelId, - "messages", IMPORTANCE_DEFAULT); - friend.setConversationId(parent.getId(), conversationId); - mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); - ArrayList<StatsEvent> events = new ArrayList<>(); - mHelper.pullPackageChannelPreferencesStats(events); - boolean found = false; - for (StatsEvent event : events) { - // TODO(b/153195691): inspect the content once it is possible to do so - found = true; - } - assertTrue("conversation was not in the pull", found); - } - @Test public void testGetNotificationChannel_conversationProvidedByNotCustomizedYet() { String conversationId = "friend"; @@ -3077,7 +3066,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testPlaceholderConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" @@ -3096,7 +3085,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testNormalConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" @@ -3115,7 +3104,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testNoConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, - mAppOpsManager); + mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" @@ -3477,4 +3466,151 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.setValidMessageSent(PKG_P, UID_P); assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P)); } + + @Test + public void testPullPackageChannelPreferencesStats() { + String channelId = "parent"; + String name = "messages"; + NotificationChannel fodderA = new NotificationChannel("a", "a", IMPORTANCE_LOW); + mHelper.createNotificationChannel(PKG_O, UID_O, fodderA, true, false); + NotificationChannel channel = + new NotificationChannel(channelId, name, IMPORTANCE_DEFAULT); + mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); + NotificationChannel fodderB = new NotificationChannel("b", "b", IMPORTANCE_HIGH); + mHelper.createNotificationChannel(PKG_O, UID_O, fodderB, true, false); + + ArrayList<StatsEvent> events = new ArrayList<>(); + mHelper.pullPackageChannelPreferencesStats(events); + + int found = 0; + for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { + if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES + && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { + ++found; + assertEquals("uid", UID_O, builder.getValue(UID_FIELD_NUMBER)); + assertTrue("uid annotation", builder.getBooleanAnnotation( + UID_FIELD_NUMBER, ANNOTATION_ID_IS_UID)); + assertEquals("importance", IMPORTANCE_DEFAULT, builder.getValue( + IMPORTANCE_FIELD_NUMBER)); + assertEquals("name", name, builder.getValue(CHANNEL_NAME_FIELD_NUMBER)); + assertFalse("isconv", builder.getBoolean(IS_CONVERSATION_FIELD_NUMBER)); + assertFalse("deleted", builder.getBoolean(IS_DELETED_FIELD_NUMBER)); + } + } + } + + @Test + public void testPullPackageChannelPreferencesStats_one_to_one() { + NotificationChannel channelA = new NotificationChannel("a", "a", IMPORTANCE_LOW); + mHelper.createNotificationChannel(PKG_O, UID_O, channelA, true, false); + NotificationChannel channelB = new NotificationChannel("b", "b", IMPORTANCE_LOW); + mHelper.createNotificationChannel(PKG_O, UID_O, channelB, true, false); + NotificationChannel channelC = new NotificationChannel("c", "c", IMPORTANCE_HIGH); + mHelper.createNotificationChannel(PKG_O, UID_O, channelC, true, false); + + List<String> channels = new LinkedList<>(Arrays.asList("a", "b", "c")); + + ArrayList<StatsEvent> events = new ArrayList<>(); + mHelper.pullPackageChannelPreferencesStats(events); + + int found = 0; + for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { + if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES) { + Object id = builder.getValue(CHANNEL_ID_FIELD_NUMBER); + assertTrue("missing channel in the output", channels.contains(id)); + channels.remove(id); + } + } + assertTrue("unexpected channel in output", channels.isEmpty()); + } + + @Test + public void testPullPackageChannelPreferencesStats_conversation() { + String conversationId = "friend"; + + NotificationChannel parent = + new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); + mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); + + String channelId = String.format( + CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); + String name = "conversation"; + NotificationChannel friend = new NotificationChannel(channelId, + name, IMPORTANCE_DEFAULT); + friend.setConversationId(parent.getId(), conversationId); + mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); + + ArrayList<StatsEvent> events = new ArrayList<>(); + mHelper.pullPackageChannelPreferencesStats(events); + + for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { + if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES + && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { + assertTrue("isConveration should be true", builder.getBoolean( + IS_CONVERSATION_FIELD_NUMBER)); + assertFalse("not demoted", builder.getBoolean( + IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); + assertFalse("not important", builder.getBoolean( + IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); + } + } + } + + @Test + public void testPullPackageChannelPreferencesStats_conversation_demoted() { + NotificationChannel parent = + new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); + mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); + String channelId = String.format( + CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); + NotificationChannel friend = new NotificationChannel(channelId, + "conversation", IMPORTANCE_DEFAULT); + friend.setConversationId(parent.getId(), "friend"); + friend.setDemoted(true); + mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); + + ArrayList<StatsEvent> events = new ArrayList<>(); + mHelper.pullPackageChannelPreferencesStats(events); + + for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { + if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES + && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { + assertTrue("isConveration should be true", builder.getBoolean( + IS_CONVERSATION_FIELD_NUMBER)); + assertTrue("is demoted", builder.getBoolean( + IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); + assertFalse("not important", builder.getBoolean( + IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); + } + } + } + + @Test + public void testPullPackageChannelPreferencesStats_conversation_priority() { + NotificationChannel parent = + new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); + mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); + String channelId = String.format( + CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); + NotificationChannel friend = new NotificationChannel(channelId, + "conversation", IMPORTANCE_DEFAULT); + friend.setConversationId(parent.getId(), "friend"); + friend.setImportantConversation(true); + mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); + + ArrayList<StatsEvent> events = new ArrayList<>(); + mHelper.pullPackageChannelPreferencesStats(events); + + for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { + if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES + && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { + assertTrue("isConveration should be true", builder.getBoolean( + IS_CONVERSATION_FIELD_NUMBER)); + assertFalse("not demoted", builder.getBoolean( + IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); + assertTrue("is important", builder.getBoolean( + IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); + } + } + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java b/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java new file mode 100644 index 000000000000..f4f64d779d30 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java @@ -0,0 +1,133 @@ +/* + * 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.server.notification; + +import android.util.StatsEvent; + +import com.android.server.notification.SysUiStatsEvent.Builder; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Wrapper for SysUiStatsEvent that implements validation. + */ +public class WrappedSysUiStatsEvent { + + static class WrappedBuilder extends Builder { + private ArrayList<Object> mValues; + private HashMap<Integer, HashMap<Byte, Object>> mAnnotations; + private int mAtomId; + private int mLastIndex; + private boolean mBuilt; + + WrappedBuilder(StatsEvent.Builder builder) { + super(builder); + mValues = new ArrayList<>(); + mAnnotations = new HashMap<>(); + mValues.add(0); // proto fields are 1-based + } + + @Override + public Builder setAtomId(int atomId) { + mAtomId = atomId; + super.setAtomId(atomId); + return this; + } + + @Override + public Builder writeInt(int value) { + addValue(Integer.valueOf(value)); + super.writeInt(value); + return this; + } + + @Override + public Builder addBooleanAnnotation(byte annotation, boolean value) { + addAnnotation(annotation, Boolean.valueOf(value)); + super.addBooleanAnnotation(annotation, value); + return this; + } + + @Override + public Builder writeString(String value) { + addValue(value); + super.writeString(value); + return this; + } + + @Override + public Builder writeBoolean(boolean value) { + addValue(Boolean.valueOf(value)); + super.writeBoolean(value); + return this; + } + + @Override + public StatsEvent build() { + mBuilt = true; + return super.build(); + } + + public Object getValue(int index) { + return index < mValues.size() ? mValues.get(index) : null; + } + + /** useful to make assertTrue() statemetns more readable. */ + public boolean getBoolean(int index) { + return (Boolean) mValues.get(index); + } + + private void addValue(Object value) { + mLastIndex = mValues.size(); + mValues.add(value); + } + + private void addAnnotation(byte annotation, Object value) { + Integer key = Integer.valueOf(mLastIndex); + if (!mAnnotations.containsKey(key)) { + mAnnotations.put(key, new HashMap<>()); + } + mAnnotations.get(key).put(Byte.valueOf(annotation), value); + } + + public boolean getBooleanAnnotation(int i, byte a) { + return ((Boolean) mAnnotations.get(Integer.valueOf(i)).get(Byte.valueOf(a))) + .booleanValue(); + } + + public int getAtomId() { + return mAtomId; + } + } + + static class WrappedBuilderFactory extends SysUiStatsEvent.BuilderFactory { + public List<WrappedBuilder> builders; + + WrappedBuilderFactory() { + builders = new ArrayList<>(); + } + + @Override + Builder newBuilder() { + WrappedBuilder b = new WrappedBuilder(StatsEvent.newBuilder()); + builders.add(b); + return b; + } + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index 36d4888fa56e..02de408343c5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -295,6 +296,27 @@ public class AppWindowTokenTests extends WindowTestsBase { } @Test + public void testRespectTopFullscreenOrientation() { + final Configuration displayConfig = mActivity.mDisplayContent.getConfiguration(); + final Configuration activityConfig = mActivity.getConfiguration(); + mActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT); + + assertEquals(Configuration.ORIENTATION_PORTRAIT, displayConfig.orientation); + assertEquals(Configuration.ORIENTATION_PORTRAIT, activityConfig.orientation); + + final ActivityRecord topActivity = WindowTestUtils.createTestActivityRecord(mStack); + topActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); + + assertEquals(Configuration.ORIENTATION_LANDSCAPE, displayConfig.orientation); + // Although the activity requested portrait, it is not the top activity that determines + // the display orientation. So it should be able to inherit the orientation from parent. + // Otherwise its configuration will be inconsistent that its orientation is portrait but + // other screen configurations are in landscape, e.g. screenWidthDp, screenHeightDp, and + // window configuration. + assertEquals(Configuration.ORIENTATION_LANDSCAPE, activityConfig.orientation); + } + + @Test public void testReportOrientationChange() { mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 7197ce9c22aa..4ad7dff87072 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -16,7 +16,10 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -73,6 +76,8 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import android.annotation.SuppressLint; @@ -1168,6 +1173,57 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testNoFixedRotationWithPip() { + mWm.mIsFixedRotationTransformEnabled = true; + // Make resume-top really update the activity state. + doReturn(false).when(mWm.mAtmService).isBooting(); + doReturn(true).when(mWm.mAtmService).isBooted(); + // Speed up the test by a few seconds. + mWm.mAtmService.deferWindowLayout(); + doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt()); + + final DisplayContent displayContent = mWm.mRoot.getDefaultDisplay(); + final Configuration displayConfig = displayContent.getConfiguration(); + final ActivityRecord pinnedActivity = createActivityRecord(displayContent, + WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD); + final Task pinnedTask = pinnedActivity.getRootTask(); + final ActivityRecord homeActivity = WindowTestUtils.createTestActivityRecord( + displayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask()); + if (displayConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { + homeActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT); + pinnedActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); + } else { + homeActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); + pinnedActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT); + } + final int homeConfigOrientation = homeActivity.getRequestedConfigurationOrientation(); + final int pinnedConfigOrientation = pinnedActivity.getRequestedConfigurationOrientation(); + + assertEquals(homeConfigOrientation, displayConfig.orientation); + + clearInvocations(mWm); + // Leave PiP to fullscreen. The orientation can be updated from + // ActivityRecord#reportDescendantOrientationChangeIfNeeded. + pinnedTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + homeActivity.setState(ActivityStack.ActivityState.STOPPED, "test"); + + assertFalse(displayContent.hasTopFixedRotationLaunchingApp()); + verify(mWm, atLeastOnce()).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt()); + assertEquals(pinnedConfigOrientation, displayConfig.orientation); + assertFalse(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging()); + + clearInvocations(mWm); + // Enter PiP from fullscreen. The orientation can be updated from + // ensure-visibility/resume-focused-stack -> ActivityRecord#makeActiveIfNeeded -> resume. + pinnedTask.setWindowingMode(WINDOWING_MODE_PINNED); + + assertFalse(displayContent.hasTopFixedRotationLaunchingApp()); + verify(mWm, atLeastOnce()).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt()); + assertEquals(homeConfigOrientation, displayConfig.orientation); + assertTrue(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging()); + } + + @Test public void testRemoteRotation() { DisplayContent dc = createNewDisplay(); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 68bc58493f13..665cf83cd33c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -145,7 +145,8 @@ public class SizeCompatTests extends ActivityTestsBase { final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds(); // The parent configuration doesn't change since the first resolved configuration, so the - // activity should fit in the parent naturally. (size=583x700). + // activity should fit in the parent naturally (size=583x700, appBounds=[9, 100 - 592, 800], + // horizontal offset = round((600 - 583) / 2) = 9)). assertFitted(); final int offsetX = (int) ((1f + displayBounds.width() - appBounds.width()) / 2); // The bounds must be horizontal centered. @@ -160,7 +161,7 @@ public class SizeCompatTests extends ActivityTestsBase { assertFitted(); // After the orientation of activity is changed, even display is not rotated, the aspect - // ratio should be the same (appBounds=[9, 100 - 592, 800], x-offset=round((600-583)/2)=9). + // ratio should be the same (bounds=[0, 0 - 600, 600], appBounds=[0, 100 - 600, 600]). assertEquals(appBounds.width(), appBounds.height() * aspectRatio, 0.5f /* delta */); // The notch is still on top. assertEquals(mActivity.getBounds().height(), appBounds.height() + notchHeight); diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index d011dbbbe5db..ae93a81f274e 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -1113,6 +1113,7 @@ public class PackageWatchdogTest { mTestLooper.dispatchAll(); List<Set> expectedSyncRequests = List.of( + Set.of(), Set.of(APP_A), Set.of(APP_A, APP_B), Set.of(APP_A, APP_B, APP_C), diff --git a/wifi/Android.bp b/wifi/Android.bp index 0df578f2216b..83b35616286a 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -111,11 +111,6 @@ java_sdk_library { ":framework-wifi-util-lib-aidls", ], - // TODO(b/155480189) - Remove naming_scheme once references have been resolved. - // Temporary java_sdk_library component naming scheme to use to ease the transition from separate - // modules to java_sdk_library. - naming_scheme: "framework-modules", - jarjar_rules: ":wifi-jarjar-rules", installable: true, diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt index 26927e56d2fa..f0555e6ec93e 100644 --- a/wifi/jarjar-rules.txt +++ b/wifi/jarjar-rules.txt @@ -31,6 +31,7 @@ rule android.net.ip.IIpClient* com.android.wifi.x.@0 rule android.net.ip.IIpClientCallbacks* com.android.wifi.x.@0 rule android.net.ipmemorystore.Blob* com.android.wifi.x.@0 rule android.net.ipmemorystore.IOnBlobRetrievedListener* com.android.wifi.x.@0 +rule android.net.ipmemorystore.IOnStatusAndCountListener* com.android.wifi.x.@0 rule android.net.ipmemorystore.IOnStatusListener* com.android.wifi.x.@0 rule android.net.ipmemorystore.NetworkAttributesParcelable* com.android.wifi.x.@0 rule android.net.ipmemorystore.SameL3NetworkResponseParcelable* com.android.wifi.x.@0 @@ -46,7 +47,9 @@ rule android.net.NetworkFactory* com.android.wifi.x.@0 rule android.net.ip.IpClientCallbacks* com.android.wifi.x.@0 rule android.net.ip.IpClientManager* com.android.wifi.x.@0 rule android.net.ip.IpClientUtil* com.android.wifi.x.@0 +rule android.net.ipmemorystore.NetworkAttributes* com.android.wifi.x.@0 rule android.net.ipmemorystore.OnBlobRetrievedListener* com.android.wifi.x.@0 +rule android.net.ipmemorystore.OnDeleteStatusListener* com.android.wifi.x.@0 rule android.net.ipmemorystore.OnStatusListener* com.android.wifi.x.@0 rule android.net.ipmemorystore.Status* com.android.wifi.x.@0 rule android.net.networkstack.ModuleNetworkStackClient* com.android.wifi.x.@0 |