1d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian/**
2d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * Copyright (c) 2017 The Android Open Source Project
3d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian *
4d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * Licensed under the Apache License, Version 2.0 (the "License");
5d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * you may not use this file except in compliance with the License.
6d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * You may obtain a copy of the License at
7d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian *
8d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian *      http://www.apache.org/licenses/LICENSE-2.0
9d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian *
10d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * Unless required by applicable law or agreed to in writing, software
11d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * distributed under the License is distributed on an "AS IS" BASIS,
12d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * See the License for the specific language governing permissions and
14d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * limitations under the License.
15d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian */
16d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
17d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianpackage android.app;
18d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
19d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.annotation.NonNull;
20cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulianimport android.app.ActivityManager.StackInfo;
21d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.content.Context;
22d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.content.Intent;
23d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.hardware.display.DisplayManager;
24d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.hardware.display.VirtualDisplay;
25d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.hardware.input.InputManager;
26d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.os.RemoteException;
27a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenningimport android.os.UserHandle;
28d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.util.AttributeSet;
29d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.util.DisplayMetrics;
30d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.util.Log;
31f0379de259d77659af0ba40362d870fe74358745Andrii Kulianimport android.view.IWindowManager;
32d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.InputDevice;
33d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.InputEvent;
34d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.MotionEvent;
35d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.Surface;
36d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.SurfaceHolder;
37d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.SurfaceView;
38d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.ViewGroup;
39d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport android.view.WindowManager;
404b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulianimport android.view.WindowManagerGlobal;
41d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
42d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianimport dalvik.system.CloseGuard;
43d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
44cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulianimport java.util.List;
45cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
46d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian/**
47d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * Activity container that allows launching activities into itself and does input forwarding.
48d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * <p>Creation of this view is only allowed to callers who have
49d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * {@link android.Manifest.permission#INJECT_EVENTS} permission.
50d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * <p>Activity launching into this container is restricted by the same rules that apply to launching
51d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * on VirtualDisplays.
52d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian * @hide
53d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian */
54d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulianpublic class ActivityView extends ViewGroup {
55d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
56d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private static final String DISPLAY_NAME = "ActivityViewVirtualDisplay";
57d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private static final String TAG = "ActivityView";
58d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
59d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private VirtualDisplay mVirtualDisplay;
60d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private final SurfaceView mSurfaceView;
61d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private Surface mSurface;
62d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
63d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private final SurfaceCallback mSurfaceCallback;
64d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private StateCallback mActivityViewCallback;
65d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
66cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian    private IActivityManager mActivityManager;
67d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private IInputForwarder mInputForwarder;
684b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    // Temp container to store view coordinates on screen.
694b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    private final int[] mLocationOnScreen = new int[2];
70d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
71cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian    private TaskStackListener mTaskStackListener;
72cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
73d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private final CloseGuard mGuard = CloseGuard.get();
74d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private boolean mOpened; // Protected by mGuard.
75d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
76d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public ActivityView(Context context) {
77d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        this(context, null /* attrs */);
78d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
79d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
80d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public ActivityView(Context context, AttributeSet attrs) {
81d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        this(context, attrs, 0 /* defStyle */);
82d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
83d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
84d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public ActivityView(Context context, AttributeSet attrs, int defStyle) {
85d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        super(context, attrs, defStyle);
86d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
87cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        mActivityManager = ActivityManager.getService();
88d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mSurfaceView = new SurfaceView(context);
89d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mSurfaceCallback = new SurfaceCallback();
90d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mSurfaceView.getHolder().addCallback(mSurfaceCallback);
91d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        addView(mSurfaceView);
92d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
93d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mOpened = true;
94d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mGuard.open("release");
95d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
96d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
97d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /** Callback that notifies when the container is ready or destroyed. */
98d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public abstract static class StateCallback {
99d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        /**
100d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * Called when the container is ready for launching activities. Calling
101d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * {@link #startActivity(Intent)} prior to this callback will result in an
102d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * {@link IllegalStateException}.
103d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         *
104d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * @see #startActivity(Intent)
105d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         */
106d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        public abstract void onActivityViewReady(ActivityView view);
107d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        /**
108d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * Called when the container can no longer launch activities. Calling
109d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * {@link #startActivity(Intent)} after this callback will result in an
110d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * {@link IllegalStateException}.
111d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         *
112d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         * @see #startActivity(Intent)
113d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian         */
114d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        public abstract void onActivityViewDestroyed(ActivityView view);
115a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        /**
116a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning         * Called when a task is moved to the front of the stack inside the container.
117a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning         * This is a filtered version of {@link TaskStackListener}
118a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning         */
119a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        public void onTaskMovedToFront(ActivityManager.StackInfo stackInfo) { }
120d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
121d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
122d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /**
123d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * Set the callback to be notified about state changes.
124d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>This class must finish initializing before {@link #startActivity(Intent)} can be called.
125d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>Note: If the instance was ready prior to this call being made, then
126d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link StateCallback#onActivityViewReady(ActivityView)} will be called from within
127d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * this method call.
128d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
129d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @param callback The callback to report events to.
130d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
131d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see StateCallback
132d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see #startActivity(Intent)
133d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     */
134d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public void setCallback(StateCallback callback) {
135d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mActivityViewCallback = callback;
136d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
137d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mVirtualDisplay != null && mActivityViewCallback != null) {
138d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mActivityViewCallback.onActivityViewReady(this);
139d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
140d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
141d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
142d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /**
143d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * Launch a new activity into this container.
144d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>Activity resolved by the provided {@link Intent} must have
145d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
146d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * launched here. Also, if activity is not owned by the owner of this container, it must allow
147d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * embedding and the caller must have permission to embed.
148d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>Note: This class must finish initializing and
149d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
150d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * this method can be called.
151d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
152d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @param intent Intent used to launch an activity.
153d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
154d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see StateCallback
155d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see #startActivity(PendingIntent)
156d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     */
157d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public void startActivity(@NonNull Intent intent) {
158d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final ActivityOptions options = prepareActivityOptions();
159d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        getContext().startActivity(intent, options.toBundle());
160d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
161d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
162d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /**
163d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * Launch a new activity into this container.
164a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * <p>Activity resolved by the provided {@link Intent} must have
165a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
166a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * launched here. Also, if activity is not owned by the owner of this container, it must allow
167a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * embedding and the caller must have permission to embed.
168a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * <p>Note: This class must finish initializing and
169a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
170a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * this method can be called.
171a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     *
172a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * @param intent Intent used to launch an activity.
173a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * @param user The UserHandle of the user to start this activity for.
174a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     *
175a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     *
176a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * @see StateCallback
177a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * @see #startActivity(PendingIntent)
178a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     */
179a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning    public void startActivity(@NonNull Intent intent, UserHandle user) {
180a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        final ActivityOptions options = prepareActivityOptions();
181a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        getContext().startActivityAsUser(intent, options.toBundle(), user);
182a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning    }
183a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning
184a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning    /**
185a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * Launch a new activity into this container.
186d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>Activity resolved by the provided {@link PendingIntent} must have
187d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
188d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * launched here. Also, if activity is not owned by the owner of this container, it must allow
189d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * embedding and the caller must have permission to embed.
190d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>Note: This class must finish initializing and
191d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
192d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * this method can be called.
193d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
194d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @param pendingIntent Intent used to launch an activity.
195d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
196d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see StateCallback
197d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see #startActivity(Intent)
198d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     */
199d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public void startActivity(@NonNull PendingIntent pendingIntent) {
200d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final ActivityOptions options = prepareActivityOptions();
201d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        try {
202d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            pendingIntent.send(null /* context */, 0 /* code */, null /* intent */,
203d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                    null /* onFinished */, null /* handler */, null /* requiredPermission */,
204d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                    options.toBundle());
205d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        } catch (PendingIntent.CanceledException e) {
206d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            throw new RuntimeException(e);
207d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
208d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
209d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
210d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /**
211d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * Check if container is ready to launch and create {@link ActivityOptions} to target the
212d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * virtual display.
213d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     */
214d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private ActivityOptions prepareActivityOptions() {
215d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mVirtualDisplay == null) {
216d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            throw new IllegalStateException(
217d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                    "Trying to start activity before ActivityView is ready.");
218d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
219d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final ActivityOptions options = ActivityOptions.makeBasic();
220d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
221d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        return options;
222d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
223d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
224d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /**
225d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * Release this container. Activity launching will no longer be permitted.
226d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * <p>Note: Calling this method is allowed after
227d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link StateCallback#onActivityViewReady(ActivityView)} callback was triggered and before
228d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * {@link StateCallback#onActivityViewDestroyed(ActivityView)}.
229d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     *
230d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     * @see StateCallback
231d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian     */
232d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public void release() {
233d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mVirtualDisplay == null) {
234d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            throw new IllegalStateException(
235d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                    "Trying to release container that is not initialized.");
236d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
237d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        performRelease();
238d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
239d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
2404b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    /**
2414b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian     * Triggers an update of {@link ActivityView}'s location on screen to properly set touch exclude
2424b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian     * regions and avoid focus switches by touches on this view.
2434b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian     */
2444b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    public void onLocationChanged() {
2454b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        updateLocation();
2464b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    }
2474b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian
248d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    @Override
249d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public void onLayout(boolean changed, int l, int t, int r, int b) {
250d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
251d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
252d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
2534b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    /** Send current location and size to the WM to set tap exclude region for this view. */
2544b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    private void updateLocation() {
2554b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        try {
2564b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            getLocationOnScreen(mLocationOnScreen);
2574b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
2584b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian                    mLocationOnScreen[0], mLocationOnScreen[1], getWidth(), getHeight());
2594b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        } catch (RemoteException e) {
2604b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            e.rethrowAsRuntimeException();
2614b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        }
2624b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    }
2634b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian
264d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    @Override
265d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public boolean onTouchEvent(MotionEvent event) {
266d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        return injectInputEvent(event) || super.onTouchEvent(event);
267d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
268d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
269d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    @Override
270d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    public boolean onGenericMotionEvent(MotionEvent event) {
271d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
272d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            if (injectInputEvent(event)) {
273d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                return true;
274d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            }
275d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
276d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        return super.onGenericMotionEvent(event);
277d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
278d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
279d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private boolean injectInputEvent(InputEvent event) {
280d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mInputForwarder != null) {
281d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            try {
282d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                return mInputForwarder.forwardEvent(event);
283d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            } catch (RemoteException e) {
284d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                e.rethrowAsRuntimeException();
285d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            }
286d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
287d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        return false;
288d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
289d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
290d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private class SurfaceCallback implements SurfaceHolder.Callback {
291d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        @Override
292d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        public void surfaceCreated(SurfaceHolder surfaceHolder) {
293d93da5c6e21d895a49e3cc224a2dfb6fb310a70cAndrii Kulian            mSurface = mSurfaceView.getHolder().getSurface();
294d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            if (mVirtualDisplay == null) {
295d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                initVirtualDisplay();
296d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                if (mVirtualDisplay != null && mActivityViewCallback != null) {
297d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                    mActivityViewCallback.onActivityViewReady(ActivityView.this);
298d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                }
299d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            } else {
300d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                mVirtualDisplay.setSurface(surfaceHolder.getSurface());
301d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            }
3024b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            updateLocation();
303d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
304d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
305d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        @Override
306d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
307d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            if (mVirtualDisplay != null) {
308d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                mVirtualDisplay.resize(width, height, getBaseDisplayDensity());
309d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            }
3104b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            updateLocation();
311d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
312d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
313d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        @Override
314d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
315d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mSurface.release();
316d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mSurface = null;
317d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            if (mVirtualDisplay != null) {
318d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                mVirtualDisplay.setSurface(null);
319d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            }
3204b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            cleanTapExcludeRegion();
321d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
322d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
323d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
324d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private void initVirtualDisplay() {
325d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mVirtualDisplay != null) {
326d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            throw new IllegalStateException("Trying to initialize for the second time.");
327d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
328d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
329d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final int width = mSurfaceView.getWidth();
330d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final int height = mSurfaceView.getHeight();
331d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
332d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mVirtualDisplay = displayManager.createVirtualDisplay(
333d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                DISPLAY_NAME + "@" + System.identityHashCode(this),
334a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                width, height, getBaseDisplayDensity(), mSurface,
335a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
336a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                        | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
337d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mVirtualDisplay == null) {
338d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            Log.e(TAG, "Failed to initialize ActivityView");
339d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            return;
340d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
341d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
342f0379de259d77659af0ba40362d870fe74358745Andrii Kulian        final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
343f0379de259d77659af0ba40362d870fe74358745Andrii Kulian        final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
344f0379de259d77659af0ba40362d870fe74358745Andrii Kulian        try {
345f0379de259d77659af0ba40362d870fe74358745Andrii Kulian            wm.dontOverrideDisplayInfo(displayId);
346f0379de259d77659af0ba40362d870fe74358745Andrii Kulian        } catch (RemoteException e) {
347f0379de259d77659af0ba40362d870fe74358745Andrii Kulian            e.rethrowAsRuntimeException();
348f0379de259d77659af0ba40362d870fe74358745Andrii Kulian        }
349f0379de259d77659af0ba40362d870fe74358745Andrii Kulian        mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
350a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        mTaskStackListener = new TaskStackListenerImpl();
351cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        try {
352cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            mActivityManager.registerTaskStackListener(mTaskStackListener);
353cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        } catch (RemoteException e) {
354cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            Log.e(TAG, "Failed to register task stack listener", e);
355cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        }
356d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
357d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
358d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private void performRelease() {
359d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (!mOpened) {
360d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            return;
361d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
362d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
363d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
364d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
365d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mInputForwarder != null) {
366d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mInputForwarder = null;
367d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
3684b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        cleanTapExcludeRegion();
369d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
370cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        if (mTaskStackListener != null) {
371cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            try {
372cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                mActivityManager.unregisterTaskStackListener(mTaskStackListener);
373cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            } catch (RemoteException e) {
374cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                Log.e(TAG, "Failed to unregister task stack listener", e);
375cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            }
376cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            mTaskStackListener = null;
377cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        }
378cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
379d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final boolean displayReleased;
380d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mVirtualDisplay != null) {
381d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mVirtualDisplay.release();
382d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mVirtualDisplay = null;
383d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            displayReleased = true;
384d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        } else {
385d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            displayReleased = false;
386d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
387d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
388d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (mSurface != null) {
389d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mSurface.release();
390d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mSurface = null;
391d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
392d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
393d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        if (displayReleased && mActivityViewCallback != null) {
394d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            mActivityViewCallback.onActivityViewDestroyed(this);
395d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
396d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
397d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mGuard.close();
398d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        mOpened = false;
399d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
400d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
4014b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    /** Report to server that tap exclude region on hosting display should be cleared. */
4024b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    private void cleanTapExcludeRegion() {
4034b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        // Update tap exclude region with an empty rect to clean the state on server.
4044b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        try {
4054b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
4064b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian                    0 /* left */, 0 /* top */, 0 /* width */, 0 /* height */);
4074b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        } catch (RemoteException e) {
4084b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian            e.rethrowAsRuntimeException();
4094b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian        }
4104b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian    }
4114b6599e494e90904cdbae03bb9cabfcaf2d06de0Andrii Kulian
412d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    /** Get density of the hosting display. */
413d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    private int getBaseDisplayDensity() {
414d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final WindowManager wm = mContext.getSystemService(WindowManager.class);
415d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        final DisplayMetrics metrics = new DisplayMetrics();
416d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        wm.getDefaultDisplay().getMetrics(metrics);
417d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        return metrics.densityDpi;
418d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
419d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian
420d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    @Override
421d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    protected void finalize() throws Throwable {
422d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        try {
423d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            if (mGuard != null) {
424d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                mGuard.warnIfOpen();
425d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian                performRelease();
426d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            }
427d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        } finally {
428d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian            super.finalize();
429d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian        }
430d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian    }
431cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
432cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian    /**
433cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian     * A task change listener that detects background color change of the topmost stack on our
434cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian     * virtual display and updates the background of the surface view. This background will be shown
435cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian     * when surface view is resized, but the app hasn't drawn its content in new size yet.
436a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * It also calls StateCallback.onTaskMovedToFront to notify interested parties that the stack
437a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * associated with the {@link ActivityView} has had a Task moved to the front. This is useful
438a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning     * when needing to also bring the host Activity to the foreground at the same time.
439cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian     */
440a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning    private class TaskStackListenerImpl extends TaskStackListener {
441cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
442cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        @Override
443cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        public void onTaskDescriptionChanged(int taskId, ActivityManager.TaskDescription td)
444cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                throws RemoteException {
445cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            if (mVirtualDisplay == null) {
446cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                return;
447cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            }
448cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
449a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            StackInfo stackInfo = getTopMostStackInfo();
450a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            if (stackInfo == null) {
451a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                return;
452a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            }
453a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            // Found the topmost stack on target display. Now check if the topmost task's
454a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            // description changed.
455a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            if (taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
456a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                mSurfaceView.setResizeBackgroundColor(td.getBackgroundColor());
457a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            }
458a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        }
459a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning
460a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        @Override
461a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        public void onTaskMovedToFront(int taskId) throws RemoteException {
462a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            if (mActivityViewCallback  != null) {
463a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                StackInfo stackInfo = getTopMostStackInfo();
464a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                // if StackInfo was null or unrelated to the "move to front" then there's no use
465a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                // notifying the callback
466a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                if (stackInfo != null
467a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                        && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
468a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                    mActivityViewCallback.onTaskMovedToFront(stackInfo);
469a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                }
470a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            }
471a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        }
472a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning
473a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning        private StackInfo getTopMostStackInfo() throws RemoteException {
474cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            // Find the topmost task on our virtual display - it will define the background
475cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            // color of the surface view during resizing.
476cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
477cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            final List<StackInfo> stackInfoList = mActivityManager.getAllStackInfos();
478cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian
479cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            // Iterate through stacks from top to bottom.
480cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            final int stackCount = stackInfoList.size();
481cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            for (int i = 0; i < stackCount; i++) {
482cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                final StackInfo stackInfo = stackInfoList.get(i);
483cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                // Only look for stacks on our virtual display.
484cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                if (stackInfo.displayId != displayId) {
485cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                    continue;
486cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian                }
487a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                // Found the topmost stack on target display.
488a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning                return stackInfo;
489cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian            }
490a1dbe9cbfa0610107df7c47a4d5388a8e484d7d7Brad Stenning            return null;
491cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian        }
492cf8f68343209e3ea18d5219efcc5b485238a4a34Andrii Kulian    }
493d313469e28268c864ab5c0467ffb4ccf16fe36f9Andrii Kulian}
494