19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
20fbf097732137a32930d151f7ba6816a5b870c32aJeff Brownimport android.graphics.Region;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
226e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haaseimport java.util.ArrayList;
230f8ffd83745f718a476564f35a2f7fd4637275bcChet Haaseimport java.util.concurrent.CopyOnWriteArrayList;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view tree observer is used to register listeners that can be notified of global
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changes in the view tree. Such global events include, but are not limited to,
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * layout of the whole tree, beginning of the drawing pass, touch mode change....
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A ViewTreeObserver should never be instantiated by applications as it is provided
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the views hierarchy. Refer to {@link android.view.View#getViewTreeObserver()}
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for more information.
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class ViewTreeObserver {
35c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // Recursive listeners use CopyOnWriteArrayList
360f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase    private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
370f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase    private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
38c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
39c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // Non-recursive listeners use CopyOnWriteArray
40c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
41c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
42c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
43c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
44c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
45c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
46c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // These listeners cannot be mutated during dispatch
4725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    private ArrayList<OnDrawListener> mOnDrawListeners;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAlive = true;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the focus state within
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the view tree changes.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnGlobalFocusChangeListener {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the focus changes in the view tree. When
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the view tree transitions from touch mode to non-touch mode, oldFocus is null.
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * When the view tree transitions from non-touch mode to touch mode, newFocus is
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * null. When focus changes in non-touch mode (without transition from or to
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * touch mode) either oldFocus or newFocus can be null.
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param oldFocus The previously focused view, if any.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param newFocus The newly focused View, if any.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onGlobalFocusChanged(View oldFocus, View newFocus);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the global layout state
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or the visibility of views within the view tree changes.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnGlobalLayoutListener {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the global layout state or the visibility of views
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * within the view tree changes
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onGlobalLayout();
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the view tree is about to be drawn.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnPreDrawListener {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the view tree is about to be drawn. At this point, all
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * views in the tree have been measured and given a frame. Clients can use this to adjust
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * their scroll bounds or even to request a new layout before drawing occurs.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return Return true to proceed with the current drawing pass, or false to cancel.
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see android.view.View#onMeasure
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see android.view.View#onLayout
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see android.view.View#onDraw
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onPreDraw();
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * Interface definition for a callback to be invoked when the view tree is about to be drawn.
10125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
10225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public interface OnDrawListener {
10325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        /**
10425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * <p>Callback method to be invoked when the view tree is about to be drawn. At this point,
10525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * views cannot be modified in any way.</p>
10625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         *
10725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * <p>Unlike with {@link OnPreDrawListener}, this method cannot be used to cancel the
10825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * current drawing pass.</p>
10925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         *
11025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * <p>An {@link OnDrawListener} listener <strong>cannot be added or removed</strong>
11125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * from this method.</p>
11225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         *
11325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * @see android.view.View#onMeasure
11425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * @see android.view.View#onLayout
11525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * @see android.view.View#onDraw
11625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         */
11725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        public void onDraw();
11825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
11925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
12025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the touch mode changes.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnTouchModeChangeListener {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the touch mode changes.
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param isInTouchMode True if the view hierarchy is now in touch mode, false  otherwise.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onTouchModeChanged(boolean isInTouchMode);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * something in the view tree has been scrolled.
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnScrollChangedListener {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when something in the view tree
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * has been scrolled.
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onScrollChanged();
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parameters used with OnComputeInternalInsetsListener.
146935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
147935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
148935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static class InternalInsetsInfo {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Offsets from the frame of the window at which the content of
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * windows behind it should be placed.
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final Rect contentInsets = new Rect();
156c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
158fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Offsets from the frame of the window at which windows behind it
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * are visible.
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final Rect visibleInsets = new Rect();
162fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
163fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
164fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Touchable region defined relative to the origin of the frame of the window.
165fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Only used when {@link #setTouchableInsets(int)} is called with
166fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the option {@link #TOUCHABLE_INSETS_REGION}.
167fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
168fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public final Region touchableRegion = new Region();
169fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #setTouchableInsets(int)}: the entire window frame
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can be touched.
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_FRAME = 0;
175c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #setTouchableInsets(int)}: the area inside of
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the content insets can be touched.
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_CONTENT = 1;
181c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #setTouchableInsets(int)}: the area inside of
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the visible insets can be touched.
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_VISIBLE = 2;
187fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
188fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
189fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Option for {@link #setTouchableInsets(int)}: the area inside of
190fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the provided touchable region in {@link #touchableRegion} can be touched.
191fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
192fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public static final int TOUCHABLE_INSETS_REGION = 3;
193fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Set which parts of the window can be touched: either
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
197fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}.
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setTouchableInsets(int val) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTouchableInsets = val;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mTouchableInsets;
204c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void reset() {
206fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            contentInsets.setEmpty();
207fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            visibleInsets.setEmpty();
208fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            touchableRegion.setEmpty();
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTouchableInsets = TOUCHABLE_INSETS_FRAME;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
21225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        @Override
21325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        public int hashCode() {
21425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            int result = contentInsets != null ? contentInsets.hashCode() : 0;
21525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            result = 31 * result + (visibleInsets != null ? visibleInsets.hashCode() : 0);
21625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            result = 31 * result + (touchableRegion != null ? touchableRegion.hashCode() : 0);
21725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            result = 31 * result + mTouchableInsets;
21825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            return result;
21925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
22025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2211e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy        @Override
2221e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy        public boolean equals(Object o) {
22325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            if (this == o) return true;
22425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            if (o == null || getClass() != o.getClass()) return false;
22525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
22625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            InternalInsetsInfo other = (InternalInsetsInfo)o;
22725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            return mTouchableInsets == other.mTouchableInsets &&
22825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                    contentInsets.equals(other.contentInsets) &&
22925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                    visibleInsets.equals(other.visibleInsets) &&
23025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                    touchableRegion.equals(other.touchableRegion);
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void set(InternalInsetsInfo other) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contentInsets.set(other.contentInsets);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            visibleInsets.set(other.visibleInsets);
236fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            touchableRegion.set(other.touchableRegion);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTouchableInsets = other.mTouchableInsets;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
240c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when layout has
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completed and the client can compute its interior insets.
244935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
245935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
246935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnComputeInternalInsetsListener {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when layout has completed and the
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * client can compute its interior insets.
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param inoutInfo Should be filled in by the implementation with
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the information about the insets of the window.  This is called
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * with whatever values the previous OnComputeInternalInsetsListener
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * returned, if there are multiple such listeners in the window.
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onComputeInternalInsets(InternalInsetsInfo inoutInfo);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a new ViewTreeObserver. This constructor should not be called
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ViewTreeObserver() {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Merges all the listeners registered on the specified observer with the listeners
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * registered on this object. After this method is invoked, the specified observer
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will return false in {@link #isAlive()} and should not be used anymore.
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param observer The ViewTreeObserver whose listeners must be added to this observer
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void merge(ViewTreeObserver observer) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnGlobalFocusListeners != null) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnGlobalFocusListeners != null) {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalFocusListeners.addAll(observer.mOnGlobalFocusListeners);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalFocusListeners = observer.mOnGlobalFocusListeners;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnGlobalLayoutListeners != null) {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnGlobalLayoutListeners != null) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalLayoutListeners.addAll(observer.mOnGlobalLayoutListeners);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalLayoutListeners = observer.mOnGlobalLayoutListeners;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnPreDrawListeners != null) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnPreDrawListeners != null) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnPreDrawListeners.addAll(observer.mOnPreDrawListeners);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnPreDrawListeners = observer.mOnPreDrawListeners;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnTouchModeChangeListeners != null) {
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnTouchModeChangeListeners != null) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnTouchModeChangeListeners = observer.mOnTouchModeChangeListeners;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnComputeInternalInsetsListeners != null) {
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnComputeInternalInsetsListeners != null) {
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnComputeInternalInsetsListeners.addAll(observer.mOnComputeInternalInsetsListeners);
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnComputeInternalInsetsListeners = observer.mOnComputeInternalInsetsListeners;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
315757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy        if (observer.mOnScrollChangedListeners != null) {
316757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy            if (mOnScrollChangedListeners != null) {
317757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy                mOnScrollChangedListeners.addAll(observer.mOnScrollChangedListeners);
318757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy            } else {
319757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy                mOnScrollChangedListeners = observer.mOnScrollChangedListeners;
320757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy            }
321757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy        }
322757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        observer.kill();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the focus state within the view tree changes.
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener listener) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalFocusListeners == null) {
3370f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalFocusListeners.add(listener);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed focus change callback.
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener)
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnGlobalFocusChangeListener(OnGlobalFocusChangeListener victim) {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalFocusListeners == null) {
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalFocusListeners.remove(victim);
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the global layout state or the visibility of views
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * within the view tree changes
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalLayoutListeners == null) {
372c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalLayoutListeners.add(listener);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed global layout callback
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
3841e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
3851e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @deprecated Use #removeOnGlobalLayoutListener instead
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3891e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    @Deprecated
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {
3911e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy        removeOnGlobalLayoutListener(victim);
3921e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    }
3931e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy
3941e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    /**
3951e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * Remove a previously installed global layout callback
3961e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
3971e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @param victim The callback to remove
3981e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
3991e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @throws IllegalStateException If {@link #isAlive()} returns false
4001e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
4011e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
4021e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     */
4031e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    public void removeOnGlobalLayoutListener(OnGlobalLayoutListener victim) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalLayoutListeners == null) {
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalLayoutListeners.remove(victim);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the view tree is about to be drawn
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnPreDrawListener(OnPreDrawListener listener) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnPreDrawListeners == null) {
422c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>();
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnPreDrawListeners.add(listener);
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed pre-draw callback
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnPreDrawListener(OnPreDrawListener)
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnPreDrawListener(OnPreDrawListener victim) {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnPreDrawListeners == null) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnPreDrawListeners.remove(victim);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
44625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p>Register a callback to be invoked when the view tree is about to be drawn.</p>
44725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
44825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
44925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
45025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @param listener The callback to add
45125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
45225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @throws IllegalStateException If {@link #isAlive()} returns false
45325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
45425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public void addOnDrawListener(OnDrawListener listener) {
45525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        checkIsAlive();
45625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
45725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        if (mOnDrawListeners == null) {
45825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            mOnDrawListeners = new ArrayList<OnDrawListener>();
45925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
46025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
46125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        mOnDrawListeners.add(listener);
46225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
46325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
46425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
46525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p>Remove a previously installed pre-draw callback.</p>
46625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
46725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
46825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
46925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @param victim The callback to remove
47025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
47125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @throws IllegalStateException If {@link #isAlive()} returns false
47225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
47325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @see #addOnDrawListener(OnDrawListener)
47425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
47525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public void removeOnDrawListener(OnDrawListener victim) {
47625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        checkIsAlive();
47725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        if (mOnDrawListeners == null) {
47825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            return;
47925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
48025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        mOnDrawListeners.remove(victim);
48125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
48225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
48325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when a view has been scrolled.
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnScrollChangedListener(OnScrollChangedListener listener) {
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnScrollChangedListeners == null) {
494c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>();
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnScrollChangedListeners.add(listener);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed scroll-changed callback
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnScrollChangedListener(OnScrollChangedListener)
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnScrollChangedListener(OnScrollChangedListener victim) {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnScrollChangedListeners == null) {
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnScrollChangedListeners.remove(victim);
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the invoked when the touch mode changes.
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnTouchModeChangeListener(OnTouchModeChangeListener listener) {
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnTouchModeChangeListeners == null) {
5280f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>();
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnTouchModeChangeListeners.add(listener);
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed touch mode change callback
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnTouchModeChangeListener(OnTouchModeChangeListener)
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnTouchModeChangeListener(OnTouchModeChangeListener victim) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnTouchModeChangeListeners == null) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnTouchModeChangeListeners.remove(victim);
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the invoked when it is time to
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * compute the window's internal insets.
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
558935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
559935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
560935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener listener) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnComputeInternalInsetsListeners == null) {
566105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mOnComputeInternalInsetsListeners =
567c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    new CopyOnWriteArray<OnComputeInternalInsetsListener>();
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnComputeInternalInsetsListeners.add(listener);
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed internal insets computation callback
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener)
581935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
582935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
583935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnComputeInternalInsetsListener(OnComputeInternalInsetsListener victim) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnComputeInternalInsetsListeners == null) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnComputeInternalInsetsListeners.remove(victim);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkIsAlive() {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mAlive) {
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("This ViewTreeObserver is not alive, call "
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "getViewTreeObserver() again");
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicates whether this ViewTreeObserver is alive. When an observer is not alive,
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * any call to a method (except this one) will throw an exception.
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If an application keeps a long-lived reference to this ViewTreeObserver, it should
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * always check for the result of this method before calling any other method.
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if this object is alive and be used, false otherwise.
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isAlive() {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAlive;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Marks this ViewTreeObserver as not alive. After invoking this method, invoking
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * any other method but {@link #isAlive()} and {@link #kill()} will throw an Exception.
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void kill() {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAlive = false;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that focus has changed.
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) {
627105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
628105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
629105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
630105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
6310f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase        final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners;
6326e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
6330f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            for (OnGlobalFocusChangeListener listener : listeners) {
6340f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase                listener.onGlobalFocusChanged(oldFocus, newFocus);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that a global layout happened. This can be called
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * manually if you are forcing a layout on a View or a hierarchy of Views that are
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not attached to a Window or in the GONE state.
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final void dispatchOnGlobalLayout() {
645105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
646105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
647105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
648105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
649c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
6506e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
651c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
652c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
653c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
654c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
655c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    access.get(i).onGlobalLayout();
656c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
657c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
658c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that the drawing pass is about to start. If a
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * listener returns true, then the drawing pass is canceled and rescheduled. This can
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called manually if you are forcing the drawing on a View or a hierarchy of Views
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that are not attached to a Window or in the GONE state.
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if the current draw should be canceled and resceduled, false otherwise.
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
67125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    @SuppressWarnings("unchecked")
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean dispatchOnPreDraw() {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean cancelDraw = false;
674c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners;
675c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        if (listeners != null && listeners.size() > 0) {
676c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start();
677c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
678c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
679c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
680c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    cancelDraw |= !(access.get(i).onPreDraw());
681c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
682c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
683c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return cancelDraw;
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
69025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * Notifies registered listeners that the drawing pass is about to start.
69125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
69225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public final void dispatchOnDraw() {
69325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        if (mOnDrawListeners != null) {
69425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            final ArrayList<OnDrawListener> listeners = mOnDrawListeners;
69525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            int numListeners = listeners.size();
69625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            for (int i = 0; i < numListeners; ++i) {
69725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                listeners.get(i).onDraw();
69825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            }
69925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
70025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
70125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
70225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that the touch mode has changed.
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param inTouchMode True if the touch mode is now enabled, false otherwise.
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnTouchModeChanged(boolean inTouchMode) {
7080f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase        final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners =
709105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mOnTouchModeChangeListeners;
7106e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
7110f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            for (OnTouchModeChangeListener listener : listeners) {
7120f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase                listener.onTouchModeChanged(inTouchMode);
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that something has scrolled.
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnScrollChanged() {
721105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
722105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
723105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
724105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
725c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
7266e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
727c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start();
728c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
729c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
730c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
731c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    access.get(i).onScrollChanged();
732c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
733c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
734c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns whether there are listeners for computing internal insets.
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean hasComputeInternalInsetsListeners() {
743c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
744105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mOnComputeInternalInsetsListeners;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (listeners != null && listeners.size() > 0);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
747c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Calls all listeners to compute the current insets.
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) {
752105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
753105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
754105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
755105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
756c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
757105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mOnComputeInternalInsetsListeners;
7586e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
759c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start();
760c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
761c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
762c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
763c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    access.get(i).onComputeInternalInsets(inoutInfo);
764c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
765c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
766c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
767c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
768c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
769c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    }
770c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
771c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    /**
772c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * Copy on write array. This array is not thread safe, and only one loop can
773c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * iterate over this array at any given time. This class avoids allocations
774c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * until a concurrent modification happens.
775c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *
776c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * Usage:
777c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *
778c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * CopyOnWriteArray.Access<MyData> access = array.start();
779c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * try {
780c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *     for (int i = 0; i < access.size(); i++) {
781c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *         MyData d = access.get(i);
782c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *     }
783c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * } finally {
784c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *     access.end();
785c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * }
786c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     */
787c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    static class CopyOnWriteArray<T> {
788c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private ArrayList<T> mData = new ArrayList<T>();
789c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private ArrayList<T> mDataCopy;
790c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
791c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private final Access<T> mAccess = new Access<T>();
792c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
793c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private boolean mStart;
794c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
795c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        static class Access<T> {
796c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            private ArrayList<T> mData;
797c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            private int mSize;
798c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
799c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            T get(int index) {
800c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                return mData.get(index);
801c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
802c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
803c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            int size() {
804c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                return mSize;
805c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
806c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
807c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
808c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        CopyOnWriteArray() {
809c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
810c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
811c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private ArrayList<T> getArray() {
812c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (mStart) {
813c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData);
814c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                return mDataCopy;
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
816c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            return mData;
817c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
818c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
819c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        Access<T> start() {
820c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (mStart) throw new IllegalStateException("Iteration already started");
821c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mStart = true;
822c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mDataCopy = null;
823c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mAccess.mData = mData;
824c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mAccess.mSize = mData.size();
825c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            return mAccess;
826c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
827c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
828c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void end() {
829c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (!mStart) throw new IllegalStateException("Iteration not started");
830c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mStart = false;
831c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (mDataCopy != null) {
832c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                mData = mDataCopy;
833c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
834c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mDataCopy = null;
835c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
836c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
837c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        int size() {
838c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            return getArray().size();
839c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
840c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
841c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void add(T item) {
842c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().add(item);
843c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
844c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
845c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void addAll(CopyOnWriteArray<T> array) {
846c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().addAll(array.mData);
847c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
848c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
849c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void remove(T item) {
850c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().remove(item);
851c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
852c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
853c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void clear() {
854c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().clear();
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
858