DisplayManagerGlobal.java revision c39d47a8e7c74bd539104b0efab898ef6fc43ddf
1088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar/*
2088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Copyright (C) 2012 The Android Open Source Project
3088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar *
4088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Licensed under the Apache License, Version 2.0 (the "License");
5088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * you may not use this file except in compliance with the License.
6088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * You may obtain a copy of the License at
7088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar *
8088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar *      http://www.apache.org/licenses/LICENSE-2.0
9088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar *
10088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Unless required by applicable law or agreed to in writing, software
11088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * distributed under the License is distributed on an "AS IS" BASIS,
12088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * See the License for the specific language governing permissions and
14088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * limitations under the License.
15088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar */
16088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
17088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarpackage android.hardware.display;
18088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
19dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millarimport android.content.Context;
200f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.hardware.display.DisplayManager.DisplayListener;
210f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.media.projection.MediaProjection;
228a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkeyimport android.media.projection.IMediaProjection;
23088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.Binder;
24088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.Handler;
25b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkeyimport android.os.IBinder;
260f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.os.Looper;
270f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.os.Message;
28088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.RemoteException;
29088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.ServiceManager;
30088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.text.TextUtils;
31088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.util.Log;
32088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.util.SparseArray;
335f123bdcde61b9fdcd58952882c621c34a727e10Dmitri Plotnikovimport android.view.DisplayAdjustments;
34088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.view.Display;
35088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.view.DisplayInfo;
36088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.view.Surface;
37088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
38088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport java.util.ArrayList;
39088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
40088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar/**
410f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * Manager communication with the display manager service on behalf of
420f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * an application process.  You're probably looking for {@link DisplayManager}.
430f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana *
440f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * @hide
450f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana */
460f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanapublic final class DisplayManagerGlobal {
470f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private static final String TAG = "DisplayManager";
480f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private static final boolean DEBUG = false;
490f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
500f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // True if display info and display ids should be cached.
510f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    //
520f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // FIXME: The cache is currently disabled because it's unclear whether we have the
530f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // necessary guarantees that the caches will always be flushed before clients
540f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // attempt to observe their new state.  For example, depending on the order
550f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // in which the binder transactions take place, we might have a problem where
560f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // an application could start processing a configuration change due to a display
570f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    // orientation change before the display info cache has actually been invalidated.
580f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private static final boolean USE_CACHE = false;
590f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
600f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    public static final int EVENT_DISPLAY_ADDED = 1;
610f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    public static final int EVENT_DISPLAY_CHANGED = 2;
620f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    public static final int EVENT_DISPLAY_REMOVED = 3;
630f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
640f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private static DisplayManagerGlobal sInstance;
650f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
660f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private final Object mLock = new Object();
670f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
680f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private final IDisplayManager mDm;
690f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
700f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private DisplayManagerCallback mCallback;
710f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
720f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana            new ArrayList<DisplayListenerDelegate>();
730f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
740f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
750f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private int[] mDisplayIdCache;
760f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
770f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private int mWifiDisplayScanNestCount;
780f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
790f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    private DisplayManagerGlobal(IDisplayManager dm) {
800f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana        mDm = dm;
810f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana    }
820f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana
8391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    /**
8491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * Gets an instance of the display manager global singleton.
8591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     *
8691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * @return The display manager instance, may be null early in system startup
8791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * before the display manager has been fully initialized.
8891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     */
8991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    public static DisplayManagerGlobal getInstance() {
9091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        synchronized (DisplayManagerGlobal.class) {
9191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            if (sInstance == null) {
9291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
9391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                if (b != null) {
9491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
9591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                }
9691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            }
9791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            return sInstance;
9891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        }
9991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    }
10091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov
10191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    /**
10291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * Get information about a particular logical display.
10391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     *
10491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * @param displayId The logical display id.
10591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * @return Information about the specified display, or null if it does not exist.
10691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     * This object belongs to an internal cache and should be treated as if it were immutable.
10791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov     */
10891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    public DisplayInfo getDisplayInfo(int displayId) {
10991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        try {
11091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            synchronized (mLock) {
11191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                DisplayInfo info;
11291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                if (USE_CACHE) {
11391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    info = mDisplayInfoCache.get(displayId);
11491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    if (info != null) {
11591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                        return info;
11691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    }
11791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                }
11891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov
11991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                info = mDm.getDisplayInfo(displayId);
12091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                if (info == null) {
12191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    return null;
12291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                }
12391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov
12491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                if (USE_CACHE) {
12591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    mDisplayInfoCache.put(displayId, info);
12691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                }
12791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                registerCallbackIfNeededLocked();
12891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov
12991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                if (DEBUG) {
13091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                    Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
13191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                }
13291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov                return info;
13391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            }
13491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        } catch (RemoteException ex) {
13591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            Log.e(TAG, "Could not get display information from display manager.", ex);
13691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            return null;
13791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        }
13891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    }
139c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov
140088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    /**
141088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     * Gets all currently valid logical display ids.
142088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     *
143088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     * @return An array containing all display ids.
144088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     */
145088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    public int[] getDisplayIds() {
146088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        try {
147088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            synchronized (mLock) {
148088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                if (USE_CACHE) {
149088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    if (mDisplayIdCache != null) {
150088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                        return mDisplayIdCache;
151088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    }
152088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                }
153088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
154088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                int[] displayIds = mDm.getDisplayIds();
155088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                if (USE_CACHE) {
156088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    mDisplayIdCache = displayIds;
157088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                }
158088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                registerCallbackIfNeededLocked();
159693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov                return displayIds;
160693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov            }
161693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov        } catch (RemoteException ex) {
162693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov            Log.e(TAG, "Could not get display ids from display manager.", ex);
163693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov            return new int[] { Display.DEFAULT_DISPLAY };
164693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov        }
165693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov    }
166693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov
167693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov    /**
168693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov     * Gets information about a logical display.
169693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov     *
170c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov     * The display metrics may be adjusted to provide compatibility
171c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov     * for legacy applications or limited screen areas.
1727cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov     *
173c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov     * @param displayId The logical display id.
174c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov     * @param daj The compatibility info and activityToken.
175c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov     * @return The display object, or null if there is no display with the given id.
176c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov     */
177c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov    public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
178693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov        DisplayInfo displayInfo = getDisplayInfo(displayId);
179693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov        if (displayInfo == null) {
180088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            return null;
181088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
182088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        return new Display(this, displayId, displayInfo, daj);
183088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    }
184569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov
185088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    /**
186088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     * Gets information about a logical display without applying any compatibility metrics.
187088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     *
188088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     * @param displayId The logical display id.
189088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar     * @return The display object, or null if there is no display with the given id.
190569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov     */
191088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    public Display getRealDisplay(int displayId) {
192088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
193088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    }
194088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
195088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    /**
196b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey     * Gets information about a logical display without applying any compatibility metrics.
197b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey     *
1988a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey     * @param displayId The logical display id.
1997cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov     * @param IBinder the activity token for this display.
200b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey     * @return The display object, or null if there is no display with the given id.
201b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey     */
20255048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov    public Display getRealDisplay(int displayId, IBinder token) {
20355048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        return getCompatibleDisplay(displayId, new DisplayAdjustments(token));
20455048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov    }
20555048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov
20655048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov    public void registerDisplayListener(DisplayListener listener, Handler handler) {
20755048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        if (listener == null) {
20855048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov            throw new IllegalArgumentException("listener must not be null");
20955048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        }
21055048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov
21155048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        synchronized (mLock) {
21255048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov            int index = findDisplayListenerLocked(listener);
21355048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov            if (index < 0) {
21455048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov                mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
21555048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov                registerCallbackIfNeededLocked();
21655048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov            }
21755048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        }
21855048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov    }
21955048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov
22055048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov    public void unregisterDisplayListener(DisplayListener listener) {
22155048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        if (listener == null) {
22255048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov            throw new IllegalArgumentException("listener must not be null");
22355048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        }
22455048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov
22555048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov        synchronized (mLock) {
226088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            int index = findDisplayListenerLocked(listener);
227088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            if (index >= 0) {
228088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                DisplayListenerDelegate d = mDisplayListeners.get(index);
2297cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                d.clearEvents();
2307cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                mDisplayListeners.remove(index);
231088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            }
23291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        }
233c9ec66b68b4ec98c9b2acb10ea25cfd7f0f648a2Dmitri Plotnikov    }
234088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
235088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    private int findDisplayListenerLocked(DisplayListener listener) {
236088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        final int numListeners = mDisplayListeners.size();
2377cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        for (int i = 0; i < numListeners; i++) {
238088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            if (mDisplayListeners.get(i).mListener == listener) {
239088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                return i;
240088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            }
241088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
2427cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        return -1;
243088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    }
244088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
245d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey    private void registerCallbackIfNeededLocked() {
24602c5b45565fd3a933b5dd5a868b7db33455d697cDmitri Plotnikov        if (mCallback == null) {
247d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey            mCallback = new DisplayManagerCallback();
248d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey            try {
2497cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                mDm.registerCallback(mCallback);
2508a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            } catch (RemoteException ex) {
251161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar                Log.e(TAG, "Failed to register callback with display manager service.", ex);
252161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar                mCallback = null;
2538a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            }
2547cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        }
255161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar    }
256161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar
257161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar    private void handleDisplayEvent(int displayId, int event) {
258161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar        synchronized (mLock) {
2598a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            if (USE_CACHE) {
260dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar                mDisplayInfoCache.remove(displayId);
261dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar
2627cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
2637cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                    mDisplayIdCache = null;
264dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar                }
265dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar            }
266dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar
2678a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            final int numListeners = mDisplayListeners.size();
268dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar            for (int i = 0; i < numListeners; i++) {
269dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar                mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
2708a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            }
2717cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        }
272dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar    }
273dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar
274dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar    public void startWifiDisplayScan() {
275dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar        synchronized (mLock) {
276d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey            if (mWifiDisplayScanNestCount++ == 0) {
277b926375cdabef2e56a8212a9fa1774566f659eaeEvan Millar                registerCallbackIfNeededLocked();
278b926375cdabef2e56a8212a9fa1774566f659eaeEvan Millar                try {
279d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey                    mDm.startWifiDisplayScan();
280088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                } catch (RemoteException ex) {
281088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    Log.e(TAG, "Failed to scan for Wifi displays.", ex);
282088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                }
2837cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov            }
284088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
285088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    }
286088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
287088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    public void stopWifiDisplayScan() {
288088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        synchronized (mLock) {
2897cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov            if (--mWifiDisplayScanNestCount == 0) {
290088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                try {
291088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    mDm.stopWifiDisplayScan();
2927cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                } catch (RemoteException ex) {
293088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    Log.e(TAG, "Failed to scan for Wifi displays.", ex);
294088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                }
2958851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana            } else if (mWifiDisplayScanNestCount < 0) {
296088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                Log.wtf(TAG, "Wifi display scan nest count became negative: "
297088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                        + mWifiDisplayScanNestCount);
298088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                mWifiDisplayScanNestCount = 0;
299088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            }
300088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
301088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    }
302088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
303088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    public void connectWifiDisplay(String deviceAddress) {
304088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        if (deviceAddress == null) {
305088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            throw new IllegalArgumentException("deviceAddress must not be null");
3060918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        }
3070918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov
3080918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        try {
3097cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov            mDm.connectWifiDisplay(deviceAddress);
3107cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        } catch (RemoteException ex) {
3110918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov            Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex);
3127cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        }
3130918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov    }
3140918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov
3150918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov    public void pauseWifiDisplay() {
3160918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        try {
3170918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov            mDm.pauseWifiDisplay();
3180918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        } catch (RemoteException ex) {
3190918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov            Log.e(TAG, "Failed to pause Wifi display.", ex);
3200918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        }
3210918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov    }
3220918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov
3230918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov    public void resumeWifiDisplay() {
3240918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        try {
3250918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov            mDm.resumeWifiDisplay();
3260918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        } catch (RemoteException ex) {
3270918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov            Log.e(TAG, "Failed to resume Wifi display.", ex);
32891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov        }
32991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    }
3300918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov
33191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov    public void disconnectWifiDisplay() {
3320918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov        try {
3330918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov            mDm.disconnectWifiDisplay();
334088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        } catch (RemoteException ex) {
335088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            Log.e(TAG, "Failed to disconnect from Wifi display.", ex);
3362365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov        }
33703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana    }
3387cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov
3397cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov    public void renameWifiDisplay(String deviceAddress, String alias) {
3408a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        if (deviceAddress == null) {
341088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            throw new IllegalArgumentException("deviceAddress must not be null");
3427cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        }
343088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
344088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        try {
3452365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov            mDm.renameWifiDisplay(deviceAddress, alias);
3468a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        } catch (RemoteException ex) {
3478a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            Log.e(TAG, "Failed to rename Wifi display " + deviceAddress
3488a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    + " with alias " + alias + ".", ex);
3498a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        }
3508a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey    }
3518a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey
3528a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey    public void forgetWifiDisplay(String deviceAddress) {
3538a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        if (deviceAddress == null) {
3548a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            throw new IllegalArgumentException("deviceAddress must not be null");
3558a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        }
3568a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey
3578a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        try {
358d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov            mDm.forgetWifiDisplay(deviceAddress);
359d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov        } catch (RemoteException ex) {
360d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov            Log.e(TAG, "Failed to forget Wifi display.", ex);
361d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov        }
362facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov    }
3637cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov
364d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov    public WifiDisplayStatus getWifiDisplayStatus() {
3657cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        try {
366d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov            return mDm.getWifiDisplayStatus();
367d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov        } catch (RemoteException ex) {
368d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov            Log.e(TAG, "Failed to get Wifi display status.", ex);
3698a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            return new WifiDisplayStatus();
3708a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        }
3718a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey    }
3722365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov
3732365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov    public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
3742365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov            String name, int width, int height, int densityDpi, Surface surface, int flags,
3758a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            VirtualDisplay.Callbacks callbacks, Handler handler) {
3767cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
37791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov            throw new IllegalArgumentException("name must be non-null and non-empty");
3788a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        }
3798a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        if (width <= 0 || height <= 0 || densityDpi <= 0) {
3808a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            throw new IllegalArgumentException("width, height, and densityDpi must be "
3812365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov                    + "greater than 0");
3828a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        }
3838a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey
3848a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        VirtualDisplayCallbacks callbackWrapper = new VirtualDisplayCallbacks(callbacks, handler);
385088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
386088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        int displayId;
387facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov        try {
388088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
389088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    context.getPackageName(), name, width, height, densityDpi, surface, flags);
390088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        } catch (RemoteException ex) {
391088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            Log.e(TAG, "Could not create virtual display: " + name, ex);
392088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            return null;
393569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov        }
394088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        if (displayId < 0) {
395088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            Log.e(TAG, "Could not create virtual display: " + name);
396dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar            return null;
397dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar        }
398088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        Display display = getRealDisplay(displayId);
399088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        if (display == null) {
400088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            Log.wtf(TAG, "Could not obtain display info for newly created "
401088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    + "virtual display: " + name);
402088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            try {
4037cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov                mDm.releaseVirtualDisplay(callbackWrapper);
404088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            } catch (RemoteException ex) {
405088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            }
406088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            return null;
407088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
408088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        return new VirtualDisplay(this, display, callbackWrapper, surface);
4097cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov    }
410088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
411088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    public void setVirtualDisplaySurface(IVirtualDisplayCallbacks token, Surface surface) {
412d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov        try {
413d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov            mDm.setVirtualDisplaySurface(token, surface);
414d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov        } catch (RemoteException ex) {
415d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov            Log.w(TAG, "Failed to set virtual display surface.", ex);
416d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov        }
417d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov    }
418d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov
419d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov    public void releaseVirtualDisplay(IVirtualDisplayCallbacks token) {
420c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov        try {
421c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov            mDm.releaseVirtualDisplay(token);
422c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov        } catch (RemoteException ex) {
423c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov            Log.w(TAG, "Failed to release virtual display.", ex);
424c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov        }
425facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov    }
426c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov
427c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov    private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
428c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov        @Override
429c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov        public void onDisplayEvent(int displayId, int event) {
430facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov            if (DEBUG) {
431c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov                Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
432c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov            }
433c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov            handleDisplayEvent(displayId, event);
434c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov        }
435c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov    }
436c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov
437facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov    private static final class DisplayListenerDelegate extends Handler {
438088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public final DisplayListener mListener;
439088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
440088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
441088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
442088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            mListener = listener;
443088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
4448a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey
4458a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        public void sendDisplayEvent(int displayId, int event) {
446088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            Message msg = obtainMessage(event, displayId, 0);
447088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            sendMessage(msg);
448088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
449088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
450088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public void clearEvents() {
451088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            removeCallbacksAndMessages(null);
452088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
453088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
454088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        @Override
455088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public void handleMessage(Message msg) {
4568a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            switch (msg.what) {
4578a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                case EVENT_DISPLAY_ADDED:
4588a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    mListener.onDisplayAdded(msg.arg1);
4598a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    break;
4608a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                case EVENT_DISPLAY_CHANGED:
4618a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    mListener.onDisplayChanged(msg.arg1);
4628a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    break;
4638a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                case EVENT_DISPLAY_REMOVED:
464088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    mListener.onDisplayRemoved(msg.arg1);
465088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    break;
466088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            }
467088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
4687cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov    }
469569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov
470088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar    private final static class VirtualDisplayCallbacks extends IVirtualDisplayCallbacks.Stub {
471facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov        private VirtualDisplayCallbacksDelegate mDelegate;
472facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov
473ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar        public VirtualDisplayCallbacks(VirtualDisplay.Callbacks callbacks, Handler handler) {
4747cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov            mDelegate = new VirtualDisplayCallbacksDelegate(callbacks, handler);
475ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar        }
476ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar
477ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar        @Override // Binder call
478ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar        public void onDisplayPaused() {
479ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar            mDelegate.sendEmptyMessage(VirtualDisplayCallbacksDelegate.MSG_DISPLAY_PAUSED);
4807cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        }
4817cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov
4827cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov        @Override // Binder call
483ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar        public void onDisplayResumed() {
484ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar            mDelegate.sendEmptyMessage(VirtualDisplayCallbacksDelegate.MSG_DISPLAY_RESUMED);
485ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar        }
486ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar
48728b68e5a59289f6947dc799b66a3b503571f876eJeff Sharkey        @Override // Binder call
488c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana        public void onDisplayStopped() {
489c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana            mDelegate.sendEmptyMessage(VirtualDisplayCallbacksDelegate.MSG_DISPLAY_STOPPED);
490c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana        }
491c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana    }
492c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana
493c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana    private final static class VirtualDisplayCallbacksDelegate extends Handler {
494c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana        public static final int MSG_DISPLAY_PAUSED = 0;
495088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public static final int MSG_DISPLAY_RESUMED = 1;
496088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public static final int MSG_DISPLAY_STOPPED = 2;
497088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
498088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        private final VirtualDisplay.Callbacks mCallbacks;
499088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
500088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public VirtualDisplayCallbacksDelegate(VirtualDisplay.Callbacks callbacks,
501088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                Handler handler) {
502088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
503088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            mCallbacks = callbacks;
504088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        }
505088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar
506088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        @Override
507088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar        public void handleMessage(Message msg) {
508088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            if (mCallbacks == null) {
509088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                return;
510088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            }
511088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar            switch (msg.what) {
512088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                case MSG_DISPLAY_PAUSED:
513088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    mCallbacks.onDisplayPaused();
514088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar                    break;
5158a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                case MSG_DISPLAY_RESUMED:
5168a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    mCallbacks.onDisplayResumed();
5178a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    break;
5188a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                case MSG_DISPLAY_STOPPED:
5198a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    mCallbacks.onDisplayStopped();
5208a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey                    break;
5218a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey            }
5228a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey        }
5238a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey    }
5248a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey}
52591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov