AdaptiveIconDrawable.java revision 547010ff863e634186fddf75890b6894f1cfa6be
136e612a488511940b61f09803b270aa1c61b68e0Jason Sams/*
2dd6c8b34f172ba699954e4d3095dba8c0fd5e930Jason Sams * Copyright (C) 2017 The Android Open Source Project
336e612a488511940b61f09803b270aa1c61b68e0Jason Sams *
436e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
536e612a488511940b61f09803b270aa1c61b68e0Jason Sams * you may not use this file except in compliance with the License.
636e612a488511940b61f09803b270aa1c61b68e0Jason Sams * You may obtain a copy of the License at
736e612a488511940b61f09803b270aa1c61b68e0Jason Sams *
836e612a488511940b61f09803b270aa1c61b68e0Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
936e612a488511940b61f09803b270aa1c61b68e0Jason Sams *
1036e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Unless required by applicable law or agreed to in writing, software
1136e612a488511940b61f09803b270aa1c61b68e0Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
1236e612a488511940b61f09803b270aa1c61b68e0Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336e612a488511940b61f09803b270aa1c61b68e0Jason Sams * See the License for the specific language governing permissions and
1436e612a488511940b61f09803b270aa1c61b68e0Jason Sams * limitations under the License.
1536e612a488511940b61f09803b270aa1c61b68e0Jason Sams */
1636e612a488511940b61f09803b270aa1c61b68e0Jason Sams
1736e612a488511940b61f09803b270aa1c61b68e0Jason Samspackage android.graphics.drawable;
1836e612a488511940b61f09803b270aa1c61b68e0Jason Sams
199c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hinesimport static android.graphics.drawable.Drawable.obtainAttributes;
20c11e25c4e653124def1fb18e203b894f42106cbeTim Murray
21c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.annotation.NonNull;
22c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.annotation.Nullable;
23c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.annotation.TestApi;
24c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.pm.ActivityInfo.Config;
25c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.ColorStateList;
26c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.Resources;
27c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.Resources.Theme;
28c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.TypedArray;
29c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Bitmap;
30c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.BitmapShader;
31c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Canvas;
32c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.ColorFilter;
33a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Samsimport android.graphics.Matrix;
34c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Outline;
35c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Paint;
36c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Path;
37c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.PixelFormat;
38c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.PorterDuff.Mode;
39c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Rect;
40c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Region;
41c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Shader;
42c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Shader.TileMode;
43c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.util.AttributeSet;
44c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.util.DisplayMetrics;
45c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.util.PathParser;
463aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez
473aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandezimport com.android.internal.R;
483aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandezimport org.xmlpull.v1.XmlPullParser;
49c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport org.xmlpull.v1.XmlPullParserException;
50c11e25c4e653124def1fb18e203b894f42106cbeTim Murray
513aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandezimport java.io.IOException;
5236e612a488511940b61f09803b270aa1c61b68e0Jason Sams
5336e612a488511940b61f09803b270aa1c61b68e0Jason Sams/**
54ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams * This drawable supports two layers: foreground and background.
55718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams *
56718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * <p>The layers are clipped when rendering using the mask path defined in the device configuration.
5770d4e5024298f71edb3b04867e05568f5495b4ceJason Sams *
587d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk * <p>This class can also be created via XML inflation using <code>&lt;adaptive-icon></code> tag
59ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams * in addition to dynamic creation.
603aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk */
613aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchoukpublic class AdaptiveIconDrawable extends Drawable implements Drawable.Callback {
62718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
63718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    /**
64718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * Mask path is defined inside device configuration in following dimension: [100 x 100]
65718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * @hide
66718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     */
673aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    public static final float MASK_SIZE = 100f;
683aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    private static final float SAFEZONE_SCALE = .9f;
693aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk
703aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    /**
713aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * All four sides of the layers are padded with extra inset so as to provide
723aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * extra content to reveal within the clip path when performing affine transformations on the
733aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * layers.
743aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     *
753aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * Each layers will reserve 25% of it's width and height.
763aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     *
773aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * As a result, the view port of the layers is smaller than their intrinsic width and height.
783aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     */
793aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    private static final float EXTRA_INSET_PERCENTAGE = 1 / 4f;
803aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    private static final float DEFAULT_VIEW_PORT_SCALE = 1f / (1 + 2 * EXTRA_INSET_PERCENTAGE);
813aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk
823aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    /**
833aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * Clip path defined in {@link com.android.internal.R.string.config_icon_mask}.
843aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     */
853aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    private static Path sMask;
863aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk
873aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    /**
883aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * Scaled mask based on the view bounds.
893aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     */
909c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    private final Path mMask;
917d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    private final Matrix mMaskMatrix;
927d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    private final Region mTransparentRegion;
93918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk
94718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    private Bitmap mMaskBitmap;
959c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines
96918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk    /**
97918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk     * Indices used to access {@link #mLayerState.mChildDrawable} array for foreground and
98fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk     * background layer.
99fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk     */
100fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk    private static final int BACKGROUND_ID = 0;
101fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk    private static final int FOREGROUND_ID = 1;
102a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams
1039c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
104a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams     * State variable that maintains the {@link ChildDrawable} array.
105f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk     */
106f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    LayerState mLayerState;
107f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk
108f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    private Shader mLayersShader;
109f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    private Bitmap mLayersBitmap;
110f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk
111f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    private final Rect mTmpOutRect = new Rect();
112f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    private Rect mHotspotBounds;
113a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    private boolean mMutated;
114a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams
115a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    private boolean mSuspendChildInvalidation;
116a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    private boolean mChildRequestedInvalidation;
117fb4f5cf614091f7876c6a895ad81f00b7837cd03Jason Sams    private final Canvas mCanvas;
118fb4f5cf614091f7876c6a895ad81f00b7837cd03Jason Sams    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG |
119a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        Paint.FILTER_BITMAP_FLAG);
120718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
1213aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    /**
122a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams     * Constructor used for xml inflation.
123718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     */
12402f41705199336f808ece50d81585450e7f8f61fStephen Hines    AdaptiveIconDrawable() {
125718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        this((LayerState) null, null);
126718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    }
127718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
128ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines    /**
129718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * The one constructor to rule them all. This is called by all public
130718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * constructors to set the state and initialize local properties.
131718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     */
13252d836332f6aae74ed97fda1b53681f36710af64Stephen Hines    AdaptiveIconDrawable(@Nullable LayerState state, @Nullable Resources res) {
133718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        mLayerState = createConstantState(state, res);
134f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams
135f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams        if (sMask == null) {
136f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams            sMask = PathParser.createPathFromPathData(
137f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams                Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask));
138f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams        }
139f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams        mMask = new Path();
1401d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        mMaskMatrix = new Matrix();
1411d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        mCanvas = new Canvas();
1421d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        mTransparentRegion = new Region();
1431d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams    }
144b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams
145b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams    private ChildDrawable createChildDrawable(Drawable drawable) {
146b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        final ChildDrawable layer = new ChildDrawable(mLayerState.mDensity);
147b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        layer.mDrawable = drawable;
148b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        layer.mDrawable.setCallback(this);
149b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        mLayerState.mChildrenChangingConfigurations |=
150b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams            layer.mDrawable.getChangingConfigurations();
151b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        return layer;
152b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams    }
153b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams
154b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams    LayerState createConstantState(@Nullable LayerState state, @Nullable Resources res) {
155718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        return new LayerState(state, this, res);
156718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    }
157718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
158718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    /**
159718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * Constructor used to dynamically create this drawable.
160718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     *
161718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * @param backgroundDrawable drawable that should be rendered in the background
162b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams     * @param foregroundDrawable drawable that should be rendered in the foreground
163b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams     * @hide
164b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams     */
165b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams    public AdaptiveIconDrawable(Drawable backgroundDrawable,
166b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams            Drawable foregroundDrawable) {
167b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        this((LayerState)null, null);
168b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams        if (backgroundDrawable != null) {
169b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams            addLayer(BACKGROUND_ID, createChildDrawable(backgroundDrawable));
170768bc02d815a94ad29146f1ed60c847d1af118ccJason Sams        }
171768bc02d815a94ad29146f1ed60c847d1af118ccJason Sams        if (foregroundDrawable != null) {
1729c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines            addLayer(FOREGROUND_ID, createChildDrawable(foregroundDrawable));
173a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        }
174a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    }
175a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams
176a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    /**
177a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams     * Sets the layer to the {@param index} and invalidates cache.
178718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     *
179718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * @param index The index of the layer.
180718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     * @param layer The layer to add.
181718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams     */
182718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    private void addLayer(int index, @NonNull ChildDrawable layer) {
183718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        mLayerState.mChildren[index] = layer;
184718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        mLayerState.invalidateCache();
1858e90f2bc1fa35a2dc7bd2aab8b8241b628800218Alex Sakhartchouk    }
1868140d7b0f62a6e5b54e318c959f2d501f7ee6784Jason Sams
1878140d7b0f62a6e5b54e318c959f2d501f7ee6784Jason Sams    @Override
188718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
189718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams            @NonNull AttributeSet attrs, @Nullable Theme theme)
190718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams            throws XmlPullParserException, IOException {
191718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        super.inflate(r, parser, attrs, theme);
192ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams
19336e612a488511940b61f09803b270aa1c61b68e0Jason Sams        final LayerState state = mLayerState;
19436e612a488511940b61f09803b270aa1c61b68e0Jason Sams        if (state == null) {
1959c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines            return;
196a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        }
197a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams
198a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        // The density may have changed since the last update. This will
199a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        // apply scaling to any existing constant state properties.
200a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        final int density = Drawable.resolveDensity(r, 0);
201c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams        state.setDensity(density);
202c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams
203c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams        final ChildDrawable[] array = state.mChildren;
204c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams        for (int i = 0; i < state.mChildren.length; i++) {
205c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            final ChildDrawable layer = array[i];
206c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            layer.setDensity(density);
207c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams        }
208c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams        inflateLayers(r, parser, attrs, theme);
209c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams    }
210c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams
211c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams    /**
212c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams     * All four sides of the layers are padded with extra inset so as to provide
2139c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines     * extra content to reveal within the clip path when performing affine transformations on the
214918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk     * layers.
215918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk     */
216918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk    public static float getExtraInsetPercentage() {
217918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk        return EXTRA_INSET_PERCENTAGE;
2187d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    }
2197d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk
2207d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    /**
2213aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * Only call this method after bound is set on this drawable.
2227d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk     *
2237d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk     * @return the mask path object used to clip the drawable
2243aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     */
2257d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    public Path getIconMask() {
2267d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        return mMask;
2279c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    }
228918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk
229918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk    /**
2307d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk     * @return the foreground drawable managed by this drawable
2317d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk     */
2327d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    public Drawable getForeground() {
2337d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        return mLayerState.mChildren[FOREGROUND_ID].mDrawable;
2343aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk    }
2357d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk
2367d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    /**
2373aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk     * @return the background drawable managed by this drawable
2387d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk     */
2397d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    public Drawable getBackground() {
2403aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk        return mLayerState.mChildren[BACKGROUND_ID].mDrawable;
2417d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    }
2427d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk
2439c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    @Override
244918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk    protected void onBoundsChange(Rect bounds) {
245918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk        if (bounds.isEmpty()) {
2467d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            return;
2477d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        }
2487d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        updateLayerBounds(bounds);
2497d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    }
2503aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk
2517d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    private void updateLayerBounds(Rect bounds) {
2527d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        try {
2533aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk            suspendChildInvalidation();
2547d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            updateLayerBoundsInternal(bounds);
2557d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            updateMaskBoundsInternal(bounds);
2563aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk        } finally {
2577d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            resumeChildInvalidation();
2587d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        }
2599c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    }
260918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk
261918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk    /**
262918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk     * Set the child layer bounds bigger than the view port size by {@link #DEFAULT_VIEW_PORT_SCALE}
2637d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk     */
2647d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    private void updateLayerBoundsInternal(Rect bounds) {
2657d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        int cX = bounds.width() / 2;
2667d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        int cY = bounds.height() / 2;
2673aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk
2687d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        for (int i = 0, count = mLayerState.N_CHILDREN; i < count; i++) {
2697d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            final ChildDrawable r = mLayerState.mChildren[i];
2703aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk            if (r == null) {
2717d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk                continue;
2727d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            }
2733aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk            final Drawable d = r.mDrawable;
2747d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            if (d == null) {
2757d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk                continue;
2769c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines            }
277918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk
278918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk            int insetWidth = (int) (bounds.width() / (DEFAULT_VIEW_PORT_SCALE * 2));
2797d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            int insetHeight = (int) (bounds.height() / (DEFAULT_VIEW_PORT_SCALE * 2));
2807d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            final Rect outRect = mTmpOutRect;
2817d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk            outRect.set(cX - insetWidth, cY - insetHeight, cX + insetWidth, cY + insetHeight);
2827d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk
2833aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk            d.setBounds(outRect);
2847d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        }
2857d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    }
2863aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk
2877d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk    private void updateMaskBoundsInternal(Rect b) {
2887d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        mMaskMatrix.setScale(b.width() / MASK_SIZE, b.height() / MASK_SIZE);
2893aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk        sMask.transform(mMaskMatrix, mMask);
2907d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk
2917d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk        if (mMaskBitmap == null || mMaskBitmap.getWidth() != b.width() ||
2929c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines            mMaskBitmap.getHeight() != b.height()) {
293f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk            mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8);
294f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk            mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888);
295f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        }
296f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        mCanvas.setBitmap(mMaskBitmap);
297f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        mPaint.setShader(null);
298f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        mCanvas.drawPath(mMask, mPaint);
2999c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines
300f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        // reset everything that depends on the view bounds
301f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        mTransparentRegion.setEmpty();
302f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk        mLayersShader = null;
303f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    }
304f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk
305f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk    @Override
3069c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    public void draw(Canvas canvas) {
307a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        if (mLayersShader == null) {
308a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams            mCanvas.setBitmap(mLayersBitmap);
309a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams            for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
310a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams                if (mLayerState.mChildren[i] == null) {
311a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams                    continue;
312a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams                }
313f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams                final Drawable dr = mLayerState.mChildren[i].mDrawable;
3146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (dr != null) {
3156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    dr.draw(mCanvas);
3166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
3176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
3186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mLayersShader = new BitmapShader(mLayersBitmap, TileMode.CLAMP, TileMode.CLAMP);
3196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mPaint.setShader(mLayersShader);
320f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams        }
321f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams        if (mMaskBitmap != null) {
322f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams            Rect bounds = getBounds();
323f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams            canvas.drawBitmap(mMaskBitmap, bounds.left, bounds.top, mPaint);
3249c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines        }
325a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    }
326a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams
327a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    @Override
328a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    public void invalidateSelf() {
329a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        mLayersShader = null;
330a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        super.invalidateSelf();
3318cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    }
3326bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3336bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
3346bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void getOutline(@NonNull Outline outline) {
3356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        outline.setConvexPath(mMask);
3366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
3376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3383c0dfbab807a459622aeade4940daddf482dec66Jason Sams    /** @hide */
3398cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    @TestApi
3403c0dfbab807a459622aeade4940daddf482dec66Jason Sams    public Region getSafeZone() {
341ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams        mMaskMatrix.reset();
3429c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines        mMaskMatrix.setScale(SAFEZONE_SCALE, SAFEZONE_SCALE, getBounds().centerX(), getBounds().centerY());
343a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        Path p = new Path();
344a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        mMask.transform(mMaskMatrix, p);
345a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        Region safezoneRegion = new Region(getBounds());
346a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        safezoneRegion.setPath(p, safezoneRegion);
347a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams        return safezoneRegion;
348a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams    }
3498cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams
3506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
3516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public @Nullable Region getTransparentRegion() {
3526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (mTransparentRegion.isEmpty()) {
3536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mMask.toggleInverseFillType();
3546bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mTransparentRegion.set(getBounds());
3556bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mTransparentRegion.setPath(mMask, mTransparentRegion);
3563c0dfbab807a459622aeade4940daddf482dec66Jason Sams            mMask.toggleInverseFillType();
3578cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        }
3583c0dfbab807a459622aeade4940daddf482dec66Jason Sams        return mTransparentRegion;
3593c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
360e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams
3616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
3626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void applyTheme(@NonNull Theme t) {
3636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        super.applyTheme(t);
3646bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3656bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final LayerState state = mLayerState;
3666bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (state == null) {
367e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams            return;
368e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams        }
369e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams
370e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams        final int density = Drawable.resolveDensity(t.getResources(), 0);
371e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams        state.setDensity(density);
3726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = state.mChildren;
3746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < state.N_CHILDREN; i++) {
3756bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final ChildDrawable layer = array[i];
3766bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            layer.setDensity(density);
3776bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
378e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams            if (layer.mThemeAttrs != null) {
379e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams                final TypedArray a = t.resolveAttributes(
380e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams                    layer.mThemeAttrs, R.styleable.AdaptiveIconDrawableLayer);
381e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams                updateLayerFromTypedArray(layer, a);
3828cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                a.recycle();
3836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
3846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable d = layer.mDrawable;
3866bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (d != null && d.canApplyTheme()) {
3876bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                d.applyTheme(t);
3886bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3893c0dfbab807a459622aeade4940daddf482dec66Jason Sams                // Update cached mask of child changing configurations.
3908cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                state.mChildrenChangingConfigurations |= d.getChangingConfigurations();
3913c0dfbab807a459622aeade4940daddf482dec66Jason Sams            }
3923c0dfbab807a459622aeade4940daddf482dec66Jason Sams        }
3938cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    }
3946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
3956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    /**
3966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     * Inflates child layers using the specified parser.
3976bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     */
3986bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
3996bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            @NonNull AttributeSet attrs, @Nullable Theme theme)
4003c0dfbab807a459622aeade4940daddf482dec66Jason Sams            throws XmlPullParserException, IOException {
4018cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        final LayerState state = mLayerState;
4023c0dfbab807a459622aeade4940daddf482dec66Jason Sams
4033c0dfbab807a459622aeade4940daddf482dec66Jason Sams        final int innerDepth = parser.getDepth() + 1;
40452d836332f6aae74ed97fda1b53681f36710af64Stephen Hines        int type;
4056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        int depth;
4066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        int childIndex = 0;
4076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4086bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
4096bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (type != XmlPullParser.START_TAG) {
4106bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                continue;
41152d836332f6aae74ed97fda1b53681f36710af64Stephen Hines            }
41252d836332f6aae74ed97fda1b53681f36710af64Stephen Hines
41352d836332f6aae74ed97fda1b53681f36710af64Stephen Hines            if (depth > innerDepth) {
41452d836332f6aae74ed97fda1b53681f36710af64Stephen Hines                continue;
415ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines            }
4166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            String tagName = parser.getName();
4176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (tagName.equals("background")) {
4186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                childIndex = BACKGROUND_ID;
4196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            } else if (tagName.equals("foreground")) {
4206bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                childIndex = FOREGROUND_ID;
4216bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            } else {
422ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines                continue;
423ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines            }
424ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines
425ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines            final ChildDrawable layer = new ChildDrawable(state.mDensity);
426a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            final TypedArray a = obtainAttributes(r, theme, attrs,
4276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                R.styleable.AdaptiveIconDrawableLayer);
4286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            updateLayerFromTypedArray(layer, a);
4296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            a.recycle();
4306bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4316bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            // If the layer doesn't have a drawable or unresolved theme
4326bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            // attribute for a drawable, attempt to parse one from the child
433a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            // element. If multiple child elements exist, we'll only use the
434a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            // first one.
435a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            if (layer.mDrawable == null && (layer.mThemeAttrs == null)) {
436a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams                while ((type = parser.next()) == XmlPullParser.TEXT) {
4378cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                }
4386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (type != XmlPullParser.START_TAG) {
4396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    throw new XmlPullParserException(parser.getPositionDescription()
4406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                            + ": <foreground> or <background> tag requires a 'drawable'"
4416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                            + "attribute or child tag defining a drawable");
4426bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
4436bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4443c0dfbab807a459622aeade4940daddf482dec66Jason Sams                // We found a child drawable. Take ownership.
4458cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
4463c0dfbab807a459622aeade4940daddf482dec66Jason Sams                layer.mDrawable.setCallback(this);
4473c0dfbab807a459622aeade4940daddf482dec66Jason Sams                state.mChildrenChangingConfigurations |=
44802f41705199336f808ece50d81585450e7f8f61fStephen Hines                        layer.mDrawable.getChangingConfigurations();
4496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
4506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            addLayer(childIndex, layer);
4516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
4526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
4536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4546bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    private void updateLayerFromTypedArray(@NonNull ChildDrawable layer, @NonNull TypedArray a) {
45502f41705199336f808ece50d81585450e7f8f61fStephen Hines        final LayerState state = mLayerState;
45602f41705199336f808ece50d81585450e7f8f61fStephen Hines
45702f41705199336f808ece50d81585450e7f8f61fStephen Hines        // Account for any configuration changes.
45802f41705199336f808ece50d81585450e7f8f61fStephen Hines        state.mChildrenChangingConfigurations |= a.getChangingConfigurations();
4598cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams
4606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        // Extract the theme attributes, if any.
4616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        layer.mThemeAttrs = a.extractThemeAttrs();
4626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        Drawable dr = a.getDrawable(R.styleable.AdaptiveIconDrawableLayer_drawable);
4646bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (dr != null) {
4656bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (layer.mDrawable != null) {
466a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams                // It's possible that a drawable was already set, in which case
4678cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                // we should clear the callback. We may have also integrated the
468a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams                // drawable's changing configurations, but we don't have enough
469a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams                // information to revert that change.
4708cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                layer.mDrawable.setCallback(null);
4716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
4726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            // Take ownership of the new drawable.
4746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            layer.mDrawable = dr;
4756bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            layer.mDrawable.setCallback(this);
4766bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            state.mChildrenChangingConfigurations |=
477a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams                layer.mDrawable.getChangingConfigurations();
4788cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        }
479a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    }
480a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams
4818cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    @Override
4826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public boolean canApplyTheme() {
4836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme();
4846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
4856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4866bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    /**
4876bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     * @hide
488a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams     */
4898cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    @Override
490a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    public boolean isProjected() {
491a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        if (super.isProjected()) {
4928cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams            return true;
4936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
4946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
4956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] layers = mLayerState.mChildren;
4966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
4976bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (layers[i].mDrawable.isProjected()) {
4986bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                return true;
499a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            }
5008cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        }
501a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        return false;
502a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    }
5038cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams
5046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    /**
5056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     * Temporarily suspends child invalidation.
5066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     *
5076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     * @see #resumeChildInvalidation()
5086bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     */
5096bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    private void suspendChildInvalidation() {
510a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        mSuspendChildInvalidation = true;
5118cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    }
512a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams
513a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    /**
5148cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams     * Resumes child invalidation after suspension, immediately performing an
5156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     * invalidation if one was requested by a child during suspension.
5166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     *
5176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     * @see #suspendChildInvalidation()
5186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni     */
5196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    private void resumeChildInvalidation() {
5206bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        mSuspendChildInvalidation = false;
521a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams
5228cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        if (mChildRequestedInvalidation) {
523a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            mChildRequestedInvalidation = false;
524a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            invalidateSelf();
5258cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        }
5266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
5276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
5286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
5296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void invalidateDrawable(@NonNull Drawable who) {
5306bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (mSuspendChildInvalidation) {
5316bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mChildRequestedInvalidation = true;
532a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        } else {
5338cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams            invalidateSelf();
534a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        }
535a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    }
5368cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams
5376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
5386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
5396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        scheduleSelf(what, when);
5406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
5416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
5426bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
543a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
5448cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        unscheduleSelf(what);
545a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams    }
546a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams
5478cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    @Override
5486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public @Config int getChangingConfigurations() {
5496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return super.getChangingConfigurations() | mLayerState.getChangingConfigurations();
5506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
5516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
5526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
5536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setHotspot(float x, float y) {
554a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        final ChildDrawable[] array = mLayerState.mChildren;
5558cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
556a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            final Drawable dr = array[i].mDrawable;
557a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            if (dr != null) {
5588cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams                dr.setHotspot(x, y);
5596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
5606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
5616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
5626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
5636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
5646bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setHotspotBounds(int left, int top, int right, int bottom) {
565a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams        final ChildDrawable[] array = mLayerState.mChildren;
5668cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
567a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            final Drawable dr = array[i].mDrawable;
568a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams            if (dr != null) {
5693a2914132146f340511425d7f78540098606b512Stephen Hines                dr.setHotspotBounds(left, top, right, bottom);
5706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
5716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
5726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
5736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (mHotspotBounds == null) {
5746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mHotspotBounds = new Rect(left, top, right, bottom);
5756bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        } else {
5763a2914132146f340511425d7f78540098606b512Stephen Hines            mHotspotBounds.set(left, top, right, bottom);
5773a2914132146f340511425d7f78540098606b512Stephen Hines        }
5783a2914132146f340511425d7f78540098606b512Stephen Hines    }
5793a2914132146f340511425d7f78540098606b512Stephen Hines
5803c0dfbab807a459622aeade4940daddf482dec66Jason Sams    @Override
5816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void getHotspotBounds(Rect outRect) {
5826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (mHotspotBounds != null) {
5836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            outRect.set(mHotspotBounds);
5846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        } else {
5856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            super.getHotspotBounds(outRect);
5866bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
5873c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
5883c0dfbab807a459622aeade4940daddf482dec66Jason Sams
5893c0dfbab807a459622aeade4940daddf482dec66Jason Sams    @Override
5903c0dfbab807a459622aeade4940daddf482dec66Jason Sams    public boolean setVisible(boolean visible, boolean restart) {
5913c0dfbab807a459622aeade4940daddf482dec66Jason Sams        final boolean changed = super.setVisible(visible, restart);
5926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
5936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
5946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
5956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
5966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (dr != null) {
5976bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                dr.setVisible(visible, restart);
5983c0dfbab807a459622aeade4940daddf482dec66Jason Sams            }
5993c0dfbab807a459622aeade4940daddf482dec66Jason Sams        }
6003c0dfbab807a459622aeade4940daddf482dec66Jason Sams
6013c0dfbab807a459622aeade4940daddf482dec66Jason Sams        return changed;
6023c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
6036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setDither(boolean dither) {
6066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
6076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
6086bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
6093c0dfbab807a459622aeade4940daddf482dec66Jason Sams            if (dr != null) {
6103c0dfbab807a459622aeade4940daddf482dec66Jason Sams                dr.setDither(dither);
6113c0dfbab807a459622aeade4940daddf482dec66Jason Sams            }
6123c0dfbab807a459622aeade4940daddf482dec66Jason Sams        }
6133c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
6146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setAlpha(int alpha) {
6176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
6186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
6196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
6203c0dfbab807a459622aeade4940daddf482dec66Jason Sams            if (dr != null) {
6213c0dfbab807a459622aeade4940daddf482dec66Jason Sams                dr.setAlpha(alpha);
6223c0dfbab807a459622aeade4940daddf482dec66Jason Sams            }
6233c0dfbab807a459622aeade4940daddf482dec66Jason Sams        }
6243c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
6256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public int getAlpha() {
6286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final Drawable dr = getFirstNonNullDrawable();
6296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (dr != null) {
6306bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            return dr.getAlpha();
6313c0dfbab807a459622aeade4940daddf482dec66Jason Sams        } else {
6323c0dfbab807a459622aeade4940daddf482dec66Jason Sams            return super.getAlpha();
6333c0dfbab807a459622aeade4940daddf482dec66Jason Sams        }
6343c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
6353c0dfbab807a459622aeade4940daddf482dec66Jason Sams
6366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setColorFilter(ColorFilter colorFilter) {
6386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
6396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
6406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
6416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (dr != null) {
6423c0dfbab807a459622aeade4940daddf482dec66Jason Sams                dr.setColorFilter(colorFilter);
6433c0dfbab807a459622aeade4940daddf482dec66Jason Sams            }
6443c0dfbab807a459622aeade4940daddf482dec66Jason Sams        }
6453c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
646a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams
6476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setTintList(ColorStateList tint) {
6496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
6506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final int N = mLayerState.N_CHILDREN;
6516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < N; i++) {
6526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
653a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            if (dr != null) {
654a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams                dr.setTintList(tint);
655a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            }
656a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams        }
657a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams    }
6586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setTintMode(Mode tintMode) {
6616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
6626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final int N = mLayerState.N_CHILDREN;
6636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < N; i++) {
664a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            final Drawable dr = array[i].mDrawable;
665a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            if (dr != null) {
666a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams                dr.setTintMode(tintMode);
667a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            }
668a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams        }
6696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
6706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    private Drawable getFirstNonNullDrawable() {
6726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
6736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
6746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
675a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            if (dr != null) {
676a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams                return dr;
677a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams            }
678a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams        }
6798cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        return null;
6806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
6816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setOpacity(int opacity) {
6836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        mLayerState.mOpacityOverride = opacity;
6846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
6856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6863c0dfbab807a459622aeade4940daddf482dec66Jason Sams    @Override
6878cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    public int getOpacity() {
6883c0dfbab807a459622aeade4940daddf482dec66Jason Sams        if (mLayerState.mOpacityOverride != PixelFormat.UNKNOWN) {
6893c0dfbab807a459622aeade4940daddf482dec66Jason Sams            return mLayerState.mOpacityOverride;
6908cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        }
6916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return mLayerState.getOpacity();
6926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
6936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
6946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
6956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void setAutoMirrored(boolean mirrored) {
6966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        mLayerState.mAutoMirrored = mirrored;
6973c0dfbab807a459622aeade4940daddf482dec66Jason Sams
6988cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        final ChildDrawable[] array = mLayerState.mChildren;
69936e612a488511940b61f09803b270aa1c61b68e0Jason Sams        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
70036e612a488511940b61f09803b270aa1c61b68e0Jason Sams            final Drawable dr = array[i].mDrawable;
7018cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams            if (dr != null) {
7026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                dr.setAutoMirrored(mirrored);
7036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
7046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
7056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
7066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
708718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams    public boolean isAutoMirrored() {
7098cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams        return mLayerState.mAutoMirrored;
7103c0dfbab807a459622aeade4940daddf482dec66Jason Sams    }
71136e612a488511940b61f09803b270aa1c61b68e0Jason Sams
712836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    @Override
7136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public void jumpToCurrentState() {
7146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
7156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
7166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
7176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (dr != null) {
7186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                dr.jumpToCurrentState();
719836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
720836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
721836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    }
722836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
723836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    @Override
7246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public boolean isStateful() {
7256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return mLayerState.isStateful();
7266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
7276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
7296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    protected boolean onStateChange(int[] state) {
730836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        boolean changed = false;
731836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
732836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        final ChildDrawable[] array = mLayerState.mChildren;
733836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
734836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            final Drawable dr = array[i].mDrawable;
7356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (dr != null && dr.isStateful() && dr.setState(state)) {
7366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                changed = true;
7376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
7386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
7396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (changed) {
741836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            updateLayerBounds(getBounds());
742836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
743836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
744836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        return changed;
745836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    }
7466bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
7486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    protected boolean onLevelChange(int level) {
7496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        boolean changed = false;
7506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
752836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
753836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            final Drawable dr = array[i].mDrawable;
754836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            if (dr != null && dr.setLevel(level)) {
755836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                changed = true;
756836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
7576bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
7586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (changed) {
7606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            updateLayerBounds(getBounds());
7616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
7626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
763836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        return changed;
764836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    }
765836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
766836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    @Override
7678cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams    public int getIntrinsicWidth() {
7686bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return (int)(getMaxIntrinsicWidth() * DEFAULT_VIEW_PORT_SCALE);
7696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
7706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    private int getMaxIntrinsicWidth() {
7726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        int width = -1;
7736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
77436e612a488511940b61f09803b270aa1c61b68e0Jason Sams            final ChildDrawable r = mLayerState.mChildren[i];
7758cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams            if (r.mDrawable == null) {
77636e612a488511940b61f09803b270aa1c61b68e0Jason Sams                continue;
77736e612a488511940b61f09803b270aa1c61b68e0Jason Sams            }
778836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            final int w = r.mDrawable.getIntrinsicWidth();
7796bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (w > width) {
7806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                width = w;
7816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
7826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
7836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return width;
7846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
785836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
786836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    @Override
787836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    public int getIntrinsicHeight() {
788836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        return (int)(getMaxIntrinsicHeight() * DEFAULT_VIEW_PORT_SCALE);
789836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    }
7906bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
7916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    private int getMaxIntrinsicHeight() {
7926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        int height = -1;
7936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
7946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final ChildDrawable r = mLayerState.mChildren[i];
7956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (r.mDrawable == null) {
796836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                continue;
797836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
798836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            final int h = r.mDrawable.getIntrinsicHeight();
799836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            if (h > height) {
800836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                height = h;
8016bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
8026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
8036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return height;
8046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
8056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
8066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
807836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    public ConstantState getConstantState() {
808836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        if (mLayerState.canConstantState()) {
809836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            mLayerState.mChangingConfigurations = getChangingConfigurations();
810836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            return mLayerState;
811836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
8126bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return null;
8136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
8146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
8156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    @Override
8166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    public Drawable mutate() {
8176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        if (!mMutated && super.mutate() == this) {
818836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            mLayerState = createConstantState(mLayerState, null);
819836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
820836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                final Drawable dr = mLayerState.mChildren[i].mDrawable;
821836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                if (dr != null) {
822836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                    dr.mutate();
8236bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
8246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
8256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mMutated = true;
8266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
8276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        return this;
8286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
829836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
830836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    /**
831836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines     * @hide
832836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines     */
833836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    public void clearMutated() {
8346bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        super.clearMutated();
8356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        final ChildDrawable[] array = mLayerState.mChildren;
8366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
8376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = array[i].mDrawable;
8386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (dr != null) {
8396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                dr.clearMutated();
840836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
841836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
842836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        mMutated = false;
843836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines    }
844836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
8456bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    static class ChildDrawable {
8466bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public Drawable mDrawable;
8476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public int[] mThemeAttrs;
8486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public int mDensity = DisplayMetrics.DENSITY_DEFAULT;
8496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
8506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        ChildDrawable(int density) {
851836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            mDensity = density;
852836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
853836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
854836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        ChildDrawable(@NonNull ChildDrawable orig, @NonNull AdaptiveIconDrawable owner,
855836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                @Nullable Resources res) {
8566bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
8576bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable dr = orig.mDrawable;
8586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            final Drawable clone;
8596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (dr != null) {
8606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                final ConstantState cs = dr.getConstantState();
8616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (cs == null) {
862836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                    clone = dr;
863836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                } else if (res != null) {
864836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                    clone = cs.newDrawable(res);
865836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                } else {
866836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                    clone = cs.newDrawable();
8676bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
8686bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                clone.setCallback(owner);
8696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                clone.setBounds(dr.getBounds());
8706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                clone.setLevel(dr.getLevel());
8716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            } else {
8726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                clone = null;
873836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
874836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
875836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            mDrawable = clone;
876836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            mThemeAttrs = orig.mThemeAttrs;
877836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
8786bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mDensity = Drawable.resolveDensity(res, orig.mDensity);
8796bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
8806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
8816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public boolean canApplyTheme() {
8826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            return mThemeAttrs != null
8836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    || (mDrawable != null && mDrawable.canApplyTheme());
884836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
885836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
886836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        public final void setDensity(int targetDensity) {
887836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            if (mDensity != targetDensity) {
888836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mDensity = targetDensity;
8896bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
8906bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
8916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
8926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
8936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    static class LayerState extends ConstantState {
8946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        private int[] mThemeAttrs;
895836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
896836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        final static int N_CHILDREN = 2;
897836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        ChildDrawable[] mChildren;
898836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
899836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        int mDensity;
9006bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        int mOpacityOverride = PixelFormat.UNKNOWN;
9016bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        @Config int mChangingConfigurations;
9036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        @Config int mChildrenChangingConfigurations;
9046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        private boolean mCheckedOpacity;
906836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        private int mOpacity;
907836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
908836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        private boolean mCheckedStateful;
909836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        private boolean mIsStateful;
910836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        private boolean mAutoMirrored = false;
9116bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9126bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        LayerState(@Nullable LayerState orig, @NonNull AdaptiveIconDrawable owner,
9136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                @Nullable Resources res) {
9146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mDensity = Drawable.resolveDensity(res, orig != null ? orig.mDensity : 0);
9156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mChildren = new ChildDrawable[N_CHILDREN];
9166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (orig != null) {
917836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                final ChildDrawable[] origChildDrawable = orig.mChildren;
918836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
919836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mChangingConfigurations = orig.mChangingConfigurations;
920836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
921836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
9226bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                for (int i = 0; i < N_CHILDREN; i++) {
9236bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    final ChildDrawable or = origChildDrawable[i];
9246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    mChildren[i] = new ChildDrawable(or, owner, res);
9256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
9266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                mCheckedOpacity = orig.mCheckedOpacity;
928836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mOpacity = orig.mOpacity;
929836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mCheckedStateful = orig.mCheckedStateful;
930836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mIsStateful = orig.mIsStateful;
931836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mAutoMirrored = orig.mAutoMirrored;
932836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mThemeAttrs = orig.mThemeAttrs;
9336bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                mOpacityOverride = orig.mOpacityOverride;
9346bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            } else {
9356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                for (int i = 0; i < N_CHILDREN; i++) {
9366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    mChildren[i] = new ChildDrawable(mDensity);
9376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
9386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
939836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
940836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
941836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        public final void setDensity(int targetDensity) {
942836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            if (mDensity != targetDensity) {
943836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                mDensity = targetDensity;
9446bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
9456bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
9466bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        @Override
9486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public boolean canApplyTheme() {
9496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (mThemeAttrs != null || super.canApplyTheme()) {
950836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                return true;
951836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
952836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
953836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            final ChildDrawable[] array = mChildren;
954836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            for (int i = 0; i < N_CHILDREN; i++) {
9556bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                final ChildDrawable layer = array[i];
9566bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (layer.canApplyTheme()) {
9576bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    return true;
9586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
9596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
9606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            return false;
961836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        }
962836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
963836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        @Override
964836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        public Drawable newDrawable() {
965836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            return new AdaptiveIconDrawable(this, null);
9666bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
9676bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9686bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        @Override
9696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public Drawable newDrawable(@Nullable Resources res) {
9706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            return new AdaptiveIconDrawable(this, res);
9716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
972836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
973836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        @Override
974836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines        public @Config int getChangingConfigurations() {
975836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            return mChangingConfigurations
976836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                    | mChildrenChangingConfigurations;
9776bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
9786bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
9796bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public final int getOpacity() {
9806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            if (mCheckedOpacity) {
9816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                return mOpacity;
9826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
983836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
984836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            final ChildDrawable[] array = mChildren;
985836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
986836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            // Seek to the first non-null drawable.
987836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            int firstIndex = -1;
9886bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            for (int i = 0; i < N_CHILDREN; i++) {
9896bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (array[i].mDrawable != null) {
9906bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    firstIndex = i;
9916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    break;
9926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
9936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
994836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines
995836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            int op;
996836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            if (firstIndex >= 0) {
997836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                op = array[firstIndex].mDrawable.getOpacity();
998836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            } else {
9996bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                op = PixelFormat.TRANSPARENT;
10006bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
10016bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
10026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            // Merge all remaining non-null drawables.
10036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            for (int i = firstIndex + 1; i < N_CHILDREN; i++) {
10046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                final Drawable dr = array[i].mDrawable;
1005836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                if (dr != null) {
1006836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                    op = Drawable.resolveOpacity(op, dr.getOpacity());
1007836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines                }
1008836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines            }
1009932e78e9903342e3494983fd3463084caab4ba42Tim Murray
1010932e78e9903342e3494983fd3463084caab4ba42Tim Murray            mOpacity = op;
10116bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mCheckedOpacity = true;
10126bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            return op;
10136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
10146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
10156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        public final boolean isStateful() {
1016932e78e9903342e3494983fd3463084caab4ba42Tim Murray            if (mCheckedStateful) {
1017932e78e9903342e3494983fd3463084caab4ba42Tim Murray                return mIsStateful;
1018932e78e9903342e3494983fd3463084caab4ba42Tim Murray            }
1019932e78e9903342e3494983fd3463084caab4ba42Tim Murray
10201d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams            final ChildDrawable[] array = mChildren;
10216bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            boolean isStateful = false;
10226bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            for (int i = 0; i < N_CHILDREN; i++) {
10236bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                final Drawable dr = array[i].mDrawable;
10246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (dr != null && dr.isStateful()) {
10256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    isStateful = true;
10266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    break;
10271d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams                }
10281d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams            }
10291d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams
103065c80f824711f084c4ece9204f543a7809534294Jason Sams            mIsStateful = isStateful;
103165c80f824711f084c4ece9204f543a7809534294Jason Sams            mCheckedStateful = true;
103265c80f824711f084c4ece9204f543a7809534294Jason Sams            return isStateful;
10331d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        }
10341d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams
10351d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        public final boolean canConstantState() {
10361d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams            final ChildDrawable[] array = mChildren;
10371d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams            for (int i = 0; i < N_CHILDREN; i++) {
10386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                final Drawable dr = array[i].mDrawable;
10396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                if (dr != null && dr.getConstantState() == null) {
10406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                    return false;
10416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni                }
10426bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            }
10436bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni
10441d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams            // Don't cache the result, this method is not called very often.
1045347697710d033036c533bd6cee409c4b4c19d437Alex Sakhartchouk            return true;
10461d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        }
10471d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams
10481d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams        public void invalidateCache() {
10496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mCheckedOpacity = false;
10506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni            mCheckedStateful = false;
10516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni        }
10526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni    }
10536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni}