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