diff --git a/core/java/com/android/internal/graphics/drawable/AnimationScaleListDrawable.java b/core/java/com/android/internal/graphics/drawable/AnimationScaleListDrawable.java
new file mode 100644
index 0000000000000..11338991c0521
--- /dev/null
+++ b/core/java/com/android/internal/graphics/drawable/AnimationScaleListDrawable.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.drawable;
+
+import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
+import android.util.AttributeSet;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * An internal DrawableContainer class, used to draw different things depending on animation scale.
+ * i.e: animation scale can be 0 in battery saver mode.
+ * This class contains 2 drawable, one is animatable, the other is static. When animation scale is
+ * not 0, the animatable drawable will the drawn. Otherwise, the static drawable will be drawn.
+ *
This class implements Animatable since ProgressBar can pick this up similarly as an
+ * AnimatedVectorDrawable.
+ *
It can be defined in an XML file with the {@code }
+ * element.
+ */
+public class AnimationScaleListDrawable extends DrawableContainer implements Animatable {
+ private static final String TAG = "AnimationScaleListDrawable";
+ private AnimatedScaleListState mAnimatedScaleListState;
+ private boolean mMutated;
+
+ public AnimationScaleListDrawable() {
+ this(null, null);
+ }
+
+ private AnimationScaleListDrawable(@Nullable AnimatedScaleListState state,
+ @Nullable Resources res) {
+ // Every scale list drawable has its own constant state.
+ final AnimatedScaleListState newState = new AnimatedScaleListState(state, this, res);
+ setConstantState(newState);
+ onStateChange(getState());
+ }
+
+ /**
+ * Set the current drawable according to the animation scale. If scale is 0, then pick the
+ * static drawable, otherwise, pick the animatable drawable.
+ */
+ @Override
+ protected boolean onStateChange(int[] stateSet) {
+ final boolean changed = super.onStateChange(stateSet);
+ int idx = mAnimatedScaleListState.getCurrentDrawableIndexBasedOnScale();
+ return selectDrawable(idx) || changed;
+ }
+
+
+ @Override
+ public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Theme theme)
+ throws XmlPullParserException, IOException {
+ final TypedArray a = obtainAttributes(r, theme, attrs,
+ R.styleable.AnimationScaleListDrawable);
+ updateDensity(r);
+ a.recycle();
+
+ inflateChildElements(r, parser, attrs, theme);
+
+ onStateChange(getState());
+ }
+
+ /**
+ * Inflates child elements from XML.
+ */
+ private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Theme theme)
+ throws XmlPullParserException, IOException {
+ final AnimatedScaleListState state = mAnimatedScaleListState;
+ final int innerDepth = parser.getDepth() + 1;
+ int type;
+ int depth;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth
+ || type != XmlPullParser.END_TAG)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (depth > innerDepth || !parser.getName().equals("item")) {
+ continue;
+ }
+
+ // Either pick up the android:drawable attribute.
+ final TypedArray a = obtainAttributes(r, theme, attrs,
+ R.styleable.AnimationScaleListDrawableItem);
+ Drawable dr = a.getDrawable(R.styleable.AnimationScaleListDrawableItem_drawable);
+ a.recycle();
+
+ // Or parse the child element under - .
+ if (dr == null) {
+ while ((type = parser.next()) == XmlPullParser.TEXT) {
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException(
+ parser.getPositionDescription()
+ + ":
- tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
+ }
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
+ }
+
+ state.addDrawable(dr);
+ }
+ }
+
+ @Override
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mAnimatedScaleListState.mutate();
+ mMutated = true;
+ }
+ return this;
+ }
+
+ @Override
+ public void clearMutated() {
+ super.clearMutated();
+ mMutated = false;
+ }
+
+ @Override
+ public void start() {
+ Drawable dr = getCurrent();
+ if (dr != null && dr instanceof Animatable) {
+ ((Animatable) dr).start();
+ }
+ }
+
+ @Override
+ public void stop() {
+ Drawable dr = getCurrent();
+ if (dr != null && dr instanceof Animatable) {
+ ((Animatable) dr).stop();
+ }
+ }
+
+ @Override
+ public boolean isRunning() {
+ boolean result = false;
+ Drawable dr = getCurrent();
+ if (dr != null && dr instanceof Animatable) {
+ result = ((Animatable) dr).isRunning();
+ }
+ return result;
+ }
+
+ static class AnimatedScaleListState extends DrawableContainerState {
+ int[] mThemeAttrs = null;
+ // The index of the last static drawable.
+ int mStaticDrawableIndex = -1;
+ // The index of the last animatable drawable.
+ int mAnimatableDrawableIndex = -1;
+
+ AnimatedScaleListState(AnimatedScaleListState orig, AnimationScaleListDrawable owner,
+ Resources res) {
+ super(orig, owner, res);
+
+ if (orig != null) {
+ // Perform a shallow copy and rely on mutate() to deep-copy.
+ mThemeAttrs = orig.mThemeAttrs;
+
+ mStaticDrawableIndex = orig.mStaticDrawableIndex;
+ mAnimatableDrawableIndex = orig.mAnimatableDrawableIndex;
+ }
+
+ }
+
+ void mutate() {
+ mThemeAttrs = mThemeAttrs != null ? mThemeAttrs.clone() : null;
+ }
+
+ /**
+ * Add the drawable into the container.
+ * This class only keep track one animatable drawable, and one static. If there are multiple
+ * defined in the XML, then pick the last one.
+ */
+ int addDrawable(Drawable drawable) {
+ final int pos = addChild(drawable);
+ if (drawable instanceof Animatable) {
+ mAnimatableDrawableIndex = pos;
+ } else {
+ mStaticDrawableIndex = pos;
+ }
+ return pos;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new AnimationScaleListDrawable(this, null);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res) {
+ return new AnimationScaleListDrawable(this, res);
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || super.canApplyTheme();
+ }
+
+ public int getCurrentDrawableIndexBasedOnScale() {
+ if (ValueAnimator.getDurationScale() == 0) {
+ return mStaticDrawableIndex;
+ }
+ return mAnimatableDrawableIndex;
+ }
+ }
+
+ @Override
+ public void applyTheme(@NonNull Theme theme) {
+ super.applyTheme(theme);
+
+ onStateChange(getState());
+ }
+
+ @Override
+ protected void setConstantState(@NonNull DrawableContainerState state) {
+ super.setConstantState(state);
+
+ if (state instanceof AnimatedScaleListState) {
+ mAnimatedScaleListState = (AnimatedScaleListState) state;
+ }
+ }
+}
+
diff --git a/core/res/res/drawable/ic_refresh.xml b/core/res/res/drawable/ic_refresh.xml
index 1f671684861fb..1297407fbb8b8 100644
--- a/core/res/res/drawable/ic_refresh.xml
+++ b/core/res/res/drawable/ic_refresh.xml
@@ -21,7 +21,4 @@ Copyright (C) 2016 The Android Open Source Project
-
diff --git a/core/res/res/drawable/progress_indeterminate_anim_large_material.xml b/core/res/res/drawable/progress_indeterminate_anim_large_material.xml
new file mode 100644
index 0000000000000..560ec5af508f4
--- /dev/null
+++ b/core/res/res/drawable/progress_indeterminate_anim_large_material.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/core/res/res/drawable/progress_indeterminate_anim_medium_material.xml b/core/res/res/drawable/progress_indeterminate_anim_medium_material.xml
new file mode 100644
index 0000000000000..fbea22f443e1a
--- /dev/null
+++ b/core/res/res/drawable/progress_indeterminate_anim_medium_material.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/res/res/drawable/progress_large_material.xml b/core/res/res/drawable/progress_large_material.xml
index 526f9141d716d..ee82e35d00f5f 100644
--- a/core/res/res/drawable/progress_large_material.xml
+++ b/core/res/res/drawable/progress_large_material.xml
@@ -13,16 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/core/res/res/drawable/progress_medium_material.xml b/core/res/res/drawable/progress_medium_material.xml
index cc35816c9c3c6..5c9260069e5d0 100644
--- a/core/res/res/drawable/progress_medium_material.xml
+++ b/core/res/res/drawable/progress_medium_material.xml
@@ -13,15 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
diff --git a/core/res/res/drawable/progress_small_material.xml b/core/res/res/drawable/progress_small_material.xml
index c6e43801cdf76..cec9d9565183d 100644
--- a/core/res/res/drawable/progress_small_material.xml
+++ b/core/res/res/drawable/progress_small_material.xml
@@ -13,16 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
-
-
-
-
-
+
+
+ -
+
+
+
+
+
+
diff --git a/core/res/res/drawable/progress_static_material.xml b/core/res/res/drawable/progress_static_material.xml
new file mode 100644
index 0000000000000..b078fa93a1557
--- /dev/null
+++ b/core/res/res/drawable/progress_static_material.xml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0c085646e01fb..f273d272e41b6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5312,6 +5312,21 @@ i
+
+
+
+
+
+
+
+
+
+
+
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 7f3a4373639b7..3aca867c03470 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1422,9 +1422,10 @@ public abstract class Drawable {
/**
* Obtains styled attributes from the theme, if available, or unstyled
* resources if the theme is null.
+ * @hide
*/
- static @NonNull TypedArray obtainAttributes(@NonNull Resources res, @Nullable Theme theme,
- @NonNull AttributeSet set, @NonNull int[] attrs) {
+ protected static @NonNull TypedArray obtainAttributes(@NonNull Resources res,
+ @Nullable Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) {
if (theme == null) {
return res.obtainAttributes(set, attrs);
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index cc7f5c7cf753b..c7a3c75f3545a 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -27,8 +27,8 @@ import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
@@ -601,8 +601,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
* during inflation.
*
* @param res the resources used to inflate density-dependent values
+ * @hide
*/
- final void updateDensity(Resources res) {
+ protected final void updateDensity(Resources res) {
mDrawableContainerState.updateDensity(res);
}
@@ -711,7 +712,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
boolean mHasTintList;
boolean mHasTintMode;
- DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
+ /**
+ * @hide
+ */
+ protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
Resources res) {
mOwner = owner;
mSourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null);