blob: 98a23f2b007502ce78dbac5bc714bd96c4993574 [file] [log] [blame]
Andrii Kuliand3134692017-06-26 14:57:02 -07001/**
2 * Copyright (c) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
19import android.annotation.NonNull;
Mady Mellorc41ed322019-09-25 11:19:26 -070020import android.annotation.Nullable;
Wale Ogunwale691af682019-02-11 03:09:10 -080021import android.annotation.TestApi;
Mark Renouf7b71a5d2019-01-23 17:12:34 -050022import android.content.ComponentName;
Andrii Kuliand3134692017-06-26 14:57:02 -070023import android.content.Context;
24import android.content.Intent;
Mady Mellor1bd16752019-10-25 12:30:09 -070025import android.content.pm.LauncherApps;
26import android.content.pm.ShortcutInfo;
Issei Suzukia5dbf522019-02-01 17:58:15 +010027import android.graphics.Insets;
Yohei Yukawab4f328a2019-05-02 08:41:27 -070028import android.graphics.Matrix;
Mark Renouf89ac9882019-10-07 16:28:18 -040029import android.graphics.Point;
Mark Renoufe574ad02019-08-12 16:22:15 -040030import android.graphics.Rect;
Tiger Huang2b210c22019-03-18 21:21:26 +080031import android.graphics.Region;
Yunfan Chenb83940c2020-04-06 16:43:09 +090032import android.hardware.display.VirtualDisplay;
Mady Mellor1bd16752019-10-25 12:30:09 -070033import android.os.Bundle;
Brad Stenninga1dbe9c2018-05-02 08:29:28 -070034import android.os.UserHandle;
Andrii Kuliand3134692017-06-26 14:57:02 -070035import android.util.AttributeSet;
Issei Suzukiea5bec72020-06-19 18:14:33 +020036import android.util.DisplayMetrics;
Andrii Kuliand3134692017-06-26 14:57:02 -070037import android.util.Log;
Issei Suzukiea5bec72020-06-19 18:14:33 +020038import android.view.Display;
39import android.view.DisplayInfo;
Mark Renouf89ac9882019-10-07 16:28:18 -040040import android.view.IWindow;
Andrii Kulianf0379de2018-03-14 16:24:07 -070041import android.view.IWindowManager;
Mark Renouf041d7262019-02-06 12:09:41 -050042import android.view.KeyEvent;
chaviwff2e7d82018-11-02 11:11:27 -070043import android.view.SurfaceControl;
Andrii Kuliand3134692017-06-26 14:57:02 -070044import android.view.SurfaceHolder;
45import android.view.SurfaceView;
chaviwd44449d2019-01-02 16:33:12 -080046import android.view.View;
Andrii Kuliand3134692017-06-26 14:57:02 -070047import android.view.ViewGroup;
Tiger Huang2b210c22019-03-18 21:21:26 +080048import android.view.ViewParent;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070049import android.window.TaskEmbedder;
50import android.window.TaskOrganizerTaskEmbedder;
51import android.window.VirtualDisplayTaskEmbedder;
Andrii Kuliand3134692017-06-26 14:57:02 -070052
53import dalvik.system.CloseGuard;
54
55/**
Mark Renouf89ac9882019-10-07 16:28:18 -040056 * Task container that allows launching activities into itself.
Andrii Kuliand3134692017-06-26 14:57:02 -070057 * <p>Activity launching into this container is restricted by the same rules that apply to launching
58 * on VirtualDisplays.
59 * @hide
60 */
Wale Ogunwale691af682019-02-11 03:09:10 -080061@TestApi
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070062public class ActivityView extends ViewGroup implements android.window.TaskEmbedder.Host {
Andrii Kuliand3134692017-06-26 14:57:02 -070063
Andrii Kuliand3134692017-06-26 14:57:02 -070064 private static final String TAG = "ActivityView";
65
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070066 private android.window.TaskEmbedder mTaskEmbedder;
Mark Renouf89ac9882019-10-07 16:28:18 -040067
Andrii Kuliand3134692017-06-26 14:57:02 -070068 private final SurfaceView mSurfaceView;
Andrii Kuliand3134692017-06-26 14:57:02 -070069 private final SurfaceCallback mSurfaceCallback;
Andrii Kuliancf8f6832018-01-23 19:43:30 -080070
Andrii Kuliand3134692017-06-26 14:57:02 -070071 private final CloseGuard mGuard = CloseGuard.get();
72 private boolean mOpened; // Protected by mGuard.
73
chaviwff2e7d82018-11-02 11:11:27 -070074 private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
chaviwff2e7d82018-11-02 11:11:27 -070075
Mark Renouf89ac9882019-10-07 16:28:18 -040076 // For Host
77 private final Point mWindowPosition = new Point();
78 private final int[] mTmpArray = new int[2];
Winson Chunga1f869d2020-03-21 23:02:48 -070079 private final Rect mTmpRect = new Rect();
Mark Renouf89ac9882019-10-07 16:28:18 -040080 private final Matrix mScreenSurfaceMatrix = new Matrix();
81 private final Region mTapExcludeRegion = new Region();
Mark Renoufe574ad02019-08-12 16:22:15 -040082
Andrii Kuliand3134692017-06-26 14:57:02 -070083 public ActivityView(Context context) {
84 this(context, null /* attrs */);
85 }
86
87 public ActivityView(Context context, AttributeSet attrs) {
88 this(context, attrs, 0 /* defStyle */);
89 }
90
91 public ActivityView(Context context, AttributeSet attrs, int defStyle) {
Wale Ogunwale9e737db2018-12-17 15:42:37 -080092 this(context, attrs, defStyle, false /*singleTaskInstance*/);
93 }
94
Winson Chunga1f869d2020-03-21 23:02:48 -070095 public ActivityView(Context context, AttributeSet attrs, int defStyle,
96 boolean singleTaskInstance) {
Linus Tufvessondb1f2ec2020-04-09 17:04:32 +010097 this(context, attrs, defStyle, singleTaskInstance, false /* usePublicVirtualDisplay */);
98 }
99
100 /**
101 * This constructor let's the caller explicitly request a public virtual display as the backing
102 * display. Using a public display is not recommended as it exposes it to other applications,
103 * but it might be needed for backwards compatibility.
104 */
105 public ActivityView(
106 @NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
107 boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
shawnlinba532af2020-06-02 17:48:37 +0800108 this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay, false);
109 }
110
111 /** @hide */
112 public ActivityView(
113 @NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
114 boolean singleTaskInstance, boolean usePublicVirtualDisplay,
115 boolean disableSurfaceViewBackgroundLayer) {
Andrii Kuliand3134692017-06-26 14:57:02 -0700116 super(context, attrs, defStyle);
Winson Chunga1f869d2020-03-21 23:02:48 -0700117 if (useTaskOrganizer()) {
118 mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this);
119 } else {
Linus Tufvessondb1f2ec2020-04-09 17:04:32 +0100120 mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, singleTaskInstance,
121 usePublicVirtualDisplay);
Winson Chunga1f869d2020-03-21 23:02:48 -0700122 }
shawnlinba532af2020-06-02 17:48:37 +0800123 mSurfaceView = new SurfaceView(context, null, 0, 0, disableSurfaceViewBackgroundLayer);
lumark3f51e3c2019-07-23 21:18:17 +0800124 // Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
125 // as master to synchronize surface view's alpha value.
126 mSurfaceView.setAlpha(super.getAlpha());
Issei Suzuki006b71f2019-06-17 15:56:57 +0200127 mSurfaceView.setUseAlpha();
Andrii Kuliand3134692017-06-26 14:57:02 -0700128 mSurfaceCallback = new SurfaceCallback();
129 mSurfaceView.getHolder().addCallback(mSurfaceCallback);
130 addView(mSurfaceView);
131
132 mOpened = true;
133 mGuard.open("release");
134 }
135
136 /** Callback that notifies when the container is ready or destroyed. */
137 public abstract static class StateCallback {
Mark Renouf7b71a5d2019-01-23 17:12:34 -0500138
Andrii Kuliand3134692017-06-26 14:57:02 -0700139 /**
140 * Called when the container is ready for launching activities. Calling
141 * {@link #startActivity(Intent)} prior to this callback will result in an
142 * {@link IllegalStateException}.
143 *
144 * @see #startActivity(Intent)
145 */
146 public abstract void onActivityViewReady(ActivityView view);
Mark Renouf7b71a5d2019-01-23 17:12:34 -0500147
Andrii Kuliand3134692017-06-26 14:57:02 -0700148 /**
149 * Called when the container can no longer launch activities. Calling
150 * {@link #startActivity(Intent)} after this callback will result in an
151 * {@link IllegalStateException}.
152 *
153 * @see #startActivity(Intent)
154 */
155 public abstract void onActivityViewDestroyed(ActivityView view);
Mark Renouf7b71a5d2019-01-23 17:12:34 -0500156
157 /**
158 * Called when a task is created inside the container.
159 * This is a filtered version of {@link TaskStackListener}
160 */
161 public void onTaskCreated(int taskId, ComponentName componentName) { }
162
Brad Stenninga1dbe9c2018-05-02 08:29:28 -0700163 /**
Winson Chunga1f869d2020-03-21 23:02:48 -0700164 * Called when a task visibility changes.
165 * @hide
166 */
167 public void onTaskVisibilityChanged(int taskId, boolean visible) { }
168
169 /**
Brad Stenninga1dbe9c2018-05-02 08:29:28 -0700170 * Called when a task is moved to the front of the stack inside the container.
171 * This is a filtered version of {@link TaskStackListener}
172 */
Wale Ogunwale691af682019-02-11 03:09:10 -0800173 public void onTaskMovedToFront(int taskId) { }
Mark Renouf7b71a5d2019-01-23 17:12:34 -0500174
175 /**
176 * Called when a task is about to be removed from the stack inside the container.
177 * This is a filtered version of {@link TaskStackListener}
178 */
179 public void onTaskRemovalStarted(int taskId) { }
Winson Chunga1f869d2020-03-21 23:02:48 -0700180
181 /**
182 * Called when back is pressed on the root activity of the task.
183 * @hide
184 */
185 public void onBackPressedOnTaskRoot(int taskId) { }
Andrii Kuliand3134692017-06-26 14:57:02 -0700186 }
187
188 /**
189 * Set the callback to be notified about state changes.
190 * <p>This class must finish initializing before {@link #startActivity(Intent)} can be called.
191 * <p>Note: If the instance was ready prior to this call being made, then
192 * {@link StateCallback#onActivityViewReady(ActivityView)} will be called from within
193 * this method call.
194 *
195 * @param callback The callback to report events to.
196 *
197 * @see StateCallback
198 * @see #startActivity(Intent)
199 */
200 public void setCallback(StateCallback callback) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400201 if (callback == null) {
202 mTaskEmbedder.setListener(null);
203 return;
Andrii Kuliand3134692017-06-26 14:57:02 -0700204 }
Mark Renouf89ac9882019-10-07 16:28:18 -0400205 mTaskEmbedder.setListener(new StateCallbackAdapter(callback));
Andrii Kuliand3134692017-06-26 14:57:02 -0700206 }
207
208 /**
Mark Renouf34d04f32019-05-13 15:53:18 -0400209 * Sets the corner radius for the Activity displayed here. The corners will be
210 * cropped from the window painted by the contained Activity.
211 *
212 * @param cornerRadius the radius for the corners, in pixels
213 * @hide
214 */
215 public void setCornerRadius(float cornerRadius) {
216 mSurfaceView.setCornerRadius(cornerRadius);
217 }
218
219 /**
Mark Renoufe574ad02019-08-12 16:22:15 -0400220 * @hide
221 */
222 public float getCornerRadius() {
223 return mSurfaceView.getCornerRadius();
224 }
225
226 /**
227 * Control whether the surface is clipped to the same bounds as the View. If true, then
228 * the bounds set by {@link #setSurfaceClipBounds(Rect)} are applied to the surface as
229 * window-crop.
230 *
231 * @param clippingEnabled whether to enable surface clipping
232 * @hide
233 */
234 public void setSurfaceClippingEnabled(boolean clippingEnabled) {
235 mSurfaceView.setEnableSurfaceClipping(clippingEnabled);
236 }
237
238 /**
239 * Sets an area on the contained surface to which it will be clipped
240 * when it is drawn. Setting the value to null will remove the clip bounds
241 * and the surface will draw normally, using its full bounds.
242 *
243 * @param clipBounds The rectangular area, in the local coordinates of
244 * this view, to which future drawing operations will be clipped.
245 * @hide
246 */
247 public void setSurfaceClipBounds(Rect clipBounds) {
248 mSurfaceView.setClipBounds(clipBounds);
249 }
250
251 /**
252 * @hide
253 */
254 public boolean getSurfaceClipBounds(Rect outRect) {
255 return mSurfaceView.getClipBounds(outRect);
256 }
257
258 /**
Mady Mellor1bd16752019-10-25 12:30:09 -0700259 * Launch an activity represented by {@link ShortcutInfo} into this container.
260 * <p>The owner of this container must be allowed to access the shortcut information,
261 * as defined in {@link LauncherApps#hasShortcutHostPermission()} to use this method.
262 * <p>Activity resolved by the provided {@link ShortcutInfo} must have
263 * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
264 * launched here. Also, if activity is not owned by the owner of this container, it must allow
265 * embedding and the caller must have permission to embed.
266 * <p>Note: This class must finish initializing and
267 * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
268 * this method can be called.
269 *
270 * @param shortcut the shortcut used to launch the activity.
271 * @param options for the activity.
272 * @param sourceBounds the rect containing the source bounds of the clicked icon to open
273 * this shortcut.
274 * @see StateCallback
275 * @see LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)
276 *
277 * @hide
278 */
279 public void startShortcutActivity(@NonNull ShortcutInfo shortcut,
280 @NonNull ActivityOptions options, @Nullable Rect sourceBounds) {
281 mTaskEmbedder.startShortcutActivity(shortcut, options, sourceBounds);
282 }
283
284 /**
Andrii Kuliand3134692017-06-26 14:57:02 -0700285 * Launch a new activity into this container.
286 * <p>Activity resolved by the provided {@link Intent} must have
287 * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
288 * launched here. Also, if activity is not owned by the owner of this container, it must allow
289 * embedding and the caller must have permission to embed.
290 * <p>Note: This class must finish initializing and
291 * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
292 * this method can be called.
293 *
294 * @param intent Intent used to launch an activity.
295 *
296 * @see StateCallback
297 * @see #startActivity(PendingIntent)
298 */
299 public void startActivity(@NonNull Intent intent) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400300 mTaskEmbedder.startActivity(intent);
Andrii Kuliand3134692017-06-26 14:57:02 -0700301 }
302
303 /**
304 * Launch a new activity into this container.
Brad Stenninga1dbe9c2018-05-02 08:29:28 -0700305 * <p>Activity resolved by the provided {@link Intent} must have
306 * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
307 * launched here. Also, if activity is not owned by the owner of this container, it must allow
308 * embedding and the caller must have permission to embed.
309 * <p>Note: This class must finish initializing and
310 * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
311 * this method can be called.
312 *
313 * @param intent Intent used to launch an activity.
314 * @param user The UserHandle of the user to start this activity for.
315 *
316 *
317 * @see StateCallback
318 * @see #startActivity(PendingIntent)
319 */
320 public void startActivity(@NonNull Intent intent, UserHandle user) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400321 mTaskEmbedder.startActivity(intent, user);
Brad Stenninga1dbe9c2018-05-02 08:29:28 -0700322 }
323
324 /**
325 * Launch a new activity into this container.
Andrii Kuliand3134692017-06-26 14:57:02 -0700326 * <p>Activity resolved by the provided {@link PendingIntent} must have
327 * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
328 * launched here. Also, if activity is not owned by the owner of this container, it must allow
329 * embedding and the caller must have permission to embed.
330 * <p>Note: This class must finish initializing and
331 * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
332 * this method can be called.
333 *
334 * @param pendingIntent Intent used to launch an activity.
335 *
336 * @see StateCallback
337 * @see #startActivity(Intent)
338 */
339 public void startActivity(@NonNull PendingIntent pendingIntent) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400340 mTaskEmbedder.startActivity(pendingIntent);
Andrii Kuliand3134692017-06-26 14:57:02 -0700341 }
342
343 /**
Mady Mellor60101c92019-04-11 19:04:00 -0700344 * Launch a new activity into this container.
345 * <p>Activity resolved by the provided {@link PendingIntent} must have
346 * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
347 * launched here. Also, if activity is not owned by the owner of this container, it must allow
348 * embedding and the caller must have permission to embed.
349 * <p>Note: This class must finish initializing and
350 * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
351 * this method can be called.
352 *
353 * @param pendingIntent Intent used to launch an activity.
Mady Mellorc41ed322019-09-25 11:19:26 -0700354 * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}.
Mady Mellor60101c92019-04-11 19:04:00 -0700355 * @param options options for the activity
356 *
357 * @see StateCallback
358 * @see #startActivity(Intent)
359 */
Mady Mellorc41ed322019-09-25 11:19:26 -0700360 public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
Mady Mellor60101c92019-04-11 19:04:00 -0700361 @NonNull ActivityOptions options) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400362 mTaskEmbedder.startActivity(pendingIntent, fillInIntent, options);
Andrii Kuliand3134692017-06-26 14:57:02 -0700363 }
364
365 /**
shawnlin28062692020-06-15 13:55:51 +0800366 * Release this container if it is initialized. Activity launching will no longer be permitted.
Andrii Kuliand3134692017-06-26 14:57:02 -0700367 */
368 public void release() {
Andrii Kuliand3134692017-06-26 14:57:02 -0700369 performRelease();
370 }
371
Andrii Kulian4b6599e2018-01-15 17:24:08 -0800372 /**
Tiger Huang2b210c22019-03-18 21:21:26 +0800373 * Triggers an update of {@link ActivityView}'s location in window to properly set tap exclude
Andrii Kulian4b6599e2018-01-15 17:24:08 -0800374 * regions and avoid focus switches by touches on this view.
375 */
376 public void onLocationChanged() {
Mark Renouf89ac9882019-10-07 16:28:18 -0400377 mTaskEmbedder.notifyBoundsChanged();
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700378 }
379
Andrii Kuliand3134692017-06-26 14:57:02 -0700380 @Override
381 public void onLayout(boolean changed, int l, int t, int r, int b) {
382 mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
383 }
384
lumark3f51e3c2019-07-23 21:18:17 +0800385 /**
386 * Sets the alpha value when the content of {@link SurfaceView} needs to show or hide.
387 * <p>Note: The surface view may ignore the alpha value in some cases. Refer to
388 * {@link SurfaceView#setAlpha} for more details.
389 *
390 * @param alpha The opacity of the view.
391 */
Tiger Huang2b210c22019-03-18 21:21:26 +0800392 @Override
Issei Suzukicac2a502019-04-16 16:52:50 +0200393 public void setAlpha(float alpha) {
lumark3f51e3c2019-07-23 21:18:17 +0800394 super.setAlpha(alpha);
395
396 if (mSurfaceView != null) {
397 mSurfaceView.setAlpha(alpha);
398 }
Issei Suzukicac2a502019-04-16 16:52:50 +0200399 }
400
401 @Override
402 public float getAlpha() {
403 return mSurfaceView.getAlpha();
404 }
405
406 @Override
Tiger Huang2b210c22019-03-18 21:21:26 +0800407 public boolean gatherTransparentRegion(Region region) {
Winson Chunga1f869d2020-03-21 23:02:48 -0700408 return mTaskEmbedder.gatherTransparentRegion(region)
409 || super.gatherTransparentRegion(region);
Tiger Huang2b210c22019-03-18 21:21:26 +0800410 }
411
Andrii Kuliand3134692017-06-26 14:57:02 -0700412 private class SurfaceCallback implements SurfaceHolder.Callback {
Issei Suzukiea5bec72020-06-19 18:14:33 +0200413 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
414 private final DisplayMetrics mTempMetrics = new DisplayMetrics();
415
Andrii Kuliand3134692017-06-26 14:57:02 -0700416 @Override
417 public void surfaceCreated(SurfaceHolder surfaceHolder) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400418 if (!mTaskEmbedder.isInitialized()) {
419 initTaskEmbedder(mSurfaceView.getSurfaceControl());
Andrii Kuliand3134692017-06-26 14:57:02 -0700420 } else {
Mark Renouf89ac9882019-10-07 16:28:18 -0400421 mTmpTransaction.reparent(mTaskEmbedder.getSurfaceControl(),
Robert Carr10584fa2019-01-14 15:55:19 -0800422 mSurfaceView.getSurfaceControl()).apply();
Andrii Kuliand3134692017-06-26 14:57:02 -0700423 }
Issei Suzukiea5bec72020-06-19 18:14:33 +0200424 mTaskEmbedder.resizeTask(getWidth(), getHeight());
Mark Renouf89ac9882019-10-07 16:28:18 -0400425 mTaskEmbedder.start();
Andrii Kuliand3134692017-06-26 14:57:02 -0700426 }
427
428 @Override
429 public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
Issei Suzukiea5bec72020-06-19 18:14:33 +0200430 final Display display = getVirtualDisplay().getDisplay();
431 if (!display.getDisplayInfo(mTempDisplayInfo)) {
432 return;
433 }
434 mTempDisplayInfo.getAppMetrics(mTempMetrics);
435 if (width != mTempMetrics.widthPixels || height != mTempMetrics.heightPixels) {
436 mTaskEmbedder.resizeTask(width, height);
437 mTaskEmbedder.notifyBoundsChanged();
438 }
Andrii Kuliand3134692017-06-26 14:57:02 -0700439 }
440
441 @Override
442 public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400443 mTaskEmbedder.stop();
Andrii Kuliand3134692017-06-26 14:57:02 -0700444 }
445 }
446
chaviwd44449d2019-01-02 16:33:12 -0800447 @Override
448 protected void onVisibilityChanged(View changedView, int visibility) {
449 super.onVisibilityChanged(changedView, visibility);
450 mSurfaceView.setVisibility(visibility);
451 }
452
Mark Renouf041d7262019-02-06 12:09:41 -0500453 /**
Mady Mellor390bff42019-04-05 15:09:01 -0700454 * @return the display id of the virtual display.
455 */
456 public int getVirtualDisplayId() {
Mark Renouf89ac9882019-10-07 16:28:18 -0400457 return mTaskEmbedder.getDisplayId();
Mady Mellor390bff42019-04-05 15:09:01 -0700458 }
459
460 /**
Yunfan Chenb83940c2020-04-06 16:43:09 +0900461 * @hide
462 * @return virtual display.
463 */
464 public VirtualDisplay getVirtualDisplay() {
465 return mTaskEmbedder.getVirtualDisplay();
466 }
467
468 /**
Mark Renouf041d7262019-02-06 12:09:41 -0500469 * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the
470 * virtual display.
471 */
472 public void performBackPress() {
Mark Renouf89ac9882019-10-07 16:28:18 -0400473 mTaskEmbedder.performBackPress();
Mark Renouf041d7262019-02-06 12:09:41 -0500474 }
475
Mark Renouf89ac9882019-10-07 16:28:18 -0400476 /**
477 * Initializes the task embedder.
478 *
479 * @param parent control for the surface to parent to
480 * @return true if the task embedder has been initialized
481 */
482 private boolean initTaskEmbedder(SurfaceControl parent) {
483 if (!mTaskEmbedder.initialize(parent)) {
Andrii Kuliand3134692017-06-26 14:57:02 -0700484 Log.e(TAG, "Failed to initialize ActivityView");
Mark Renouf89ac9882019-10-07 16:28:18 -0400485 return false;
Andrii Kuliand3134692017-06-26 14:57:02 -0700486 }
Mark Renouf89ac9882019-10-07 16:28:18 -0400487 return true;
Andrii Kuliand3134692017-06-26 14:57:02 -0700488 }
489
490 private void performRelease() {
491 if (!mOpened) {
492 return;
493 }
Andrii Kuliand3134692017-06-26 14:57:02 -0700494 mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
shawnlin28062692020-06-15 13:55:51 +0800495 if (mTaskEmbedder.isInitialized()) {
496 mTaskEmbedder.release();
497 }
Yuncheol Heo9076eac2019-11-10 11:32:27 -0800498 mTaskEmbedder.setListener(null);
Andrii Kuliand3134692017-06-26 14:57:02 -0700499
500 mGuard.close();
501 mOpened = false;
502 }
503
Andrii Kuliand3134692017-06-26 14:57:02 -0700504 @Override
505 protected void finalize() throws Throwable {
506 try {
507 if (mGuard != null) {
508 mGuard.warnIfOpen();
509 performRelease();
510 }
511 } finally {
512 super.finalize();
513 }
514 }
Andrii Kuliancf8f6832018-01-23 19:43:30 -0800515
516 /**
Issei Suzukia5dbf522019-02-01 17:58:15 +0100517 * Set forwarded insets on the virtual display.
518 *
519 * @see IWindowManager#setForwardedInsets
520 */
521 public void setForwardedInsets(Insets insets) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400522 mTaskEmbedder.setForwardedInsets(insets);
523 }
524
525 // Host
526
527 /** @hide */
528 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700529 public void onTaskBackgroundColorChanged(android.window.TaskEmbedder ts, int bgColor) {
Mark Renouf89ac9882019-10-07 16:28:18 -0400530 if (mSurfaceView != null) {
531 mSurfaceView.setResizeBackgroundColor(bgColor);
Issei Suzukia5dbf522019-02-01 17:58:15 +0100532 }
533 }
534
Mark Renouf89ac9882019-10-07 16:28:18 -0400535 /** @hide */
536 @Override
537 public Region getTapExcludeRegion() {
538 if (isAttachedToWindow() && canReceivePointerEvents()) {
539 Point windowPos = getPositionInWindow();
540 mTapExcludeRegion.set(
541 windowPos.x,
542 windowPos.y,
543 windowPos.x + getWidth(),
544 windowPos.y + getHeight());
545 // There might be views on top of us. We need to subtract those areas from the tap
546 // exclude region.
547 final ViewParent parent = getParent();
548 if (parent != null) {
549 parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this);
550 }
551 } else {
552 mTapExcludeRegion.setEmpty();
553 }
554 return mTapExcludeRegion;
555 }
Andrii Kuliancf8f6832018-01-23 19:43:30 -0800556
Mark Renouf89ac9882019-10-07 16:28:18 -0400557 /** @hide */
558 @Override
559 public Matrix getScreenToTaskMatrix() {
560 getLocationOnScreen(mTmpArray);
561 mScreenSurfaceMatrix.set(getMatrix());
562 mScreenSurfaceMatrix.postTranslate(mTmpArray[0], mTmpArray[1]);
563 return mScreenSurfaceMatrix;
564 }
Andrii Kuliancf8f6832018-01-23 19:43:30 -0800565
Mark Renouf89ac9882019-10-07 16:28:18 -0400566 /** @hide */
567 @Override
568 public Point getPositionInWindow() {
569 getLocationInWindow(mTmpArray);
570 mWindowPosition.set(mTmpArray[0], mTmpArray[1]);
571 return mWindowPosition;
572 }
573
574 /** @hide */
575 @Override
Winson Chunga1f869d2020-03-21 23:02:48 -0700576 public Rect getScreenBounds() {
577 getBoundsOnScreen(mTmpRect);
578 return mTmpRect;
579 }
580
581 /** @hide */
582 @Override
Mark Renouf89ac9882019-10-07 16:28:18 -0400583 public IWindow getWindow() {
584 return super.getWindow();
585 }
586
587 /** @hide */
588 @Override
589 public boolean canReceivePointerEvents() {
590 return super.canReceivePointerEvents();
591 }
592
Winson Chunga1f869d2020-03-21 23:02:48 -0700593 /**
594 * Overridden by instances that require the use of the task organizer implementation instead of
595 * the virtual display implementation. Not for general use.
596 * @hide
597 */
598 protected boolean useTaskOrganizer() {
599 return false;
600 }
601
Mark Renouf89ac9882019-10-07 16:28:18 -0400602 private final class StateCallbackAdapter implements TaskEmbedder.Listener {
603 private final StateCallback mCallback;
604
605 private StateCallbackAdapter(ActivityView.StateCallback cb) {
606 mCallback = cb;
Brad Stenninga1dbe9c2018-05-02 08:29:28 -0700607 }
608
609 @Override
Mark Renouf89ac9882019-10-07 16:28:18 -0400610 public void onInitialized() {
611 mCallback.onActivityViewReady(ActivityView.this);
Mark Renouf7b71a5d2019-01-23 17:12:34 -0500612 }
613
614 @Override
Mark Renouf89ac9882019-10-07 16:28:18 -0400615 public void onReleased() {
616 mCallback.onActivityViewDestroyed(ActivityView.this);
Mark Renouf7b71a5d2019-01-23 17:12:34 -0500617 }
618
619 @Override
Mark Renouf89ac9882019-10-07 16:28:18 -0400620 public void onTaskCreated(int taskId, ComponentName name) {
621 mCallback.onTaskCreated(taskId, name);
Brad Stenninga1dbe9c2018-05-02 08:29:28 -0700622 }
623
Mark Renouf89ac9882019-10-07 16:28:18 -0400624 @Override
Winson Chunga1f869d2020-03-21 23:02:48 -0700625 public void onTaskVisibilityChanged(int taskId, boolean visible) {
626 mCallback.onTaskVisibilityChanged(taskId, visible);
627 }
628
629 @Override
Mark Renouf89ac9882019-10-07 16:28:18 -0400630 public void onTaskMovedToFront(int taskId) {
631 mCallback.onTaskMovedToFront(taskId);
632 }
Andrii Kuliancf8f6832018-01-23 19:43:30 -0800633
Mark Renouf89ac9882019-10-07 16:28:18 -0400634 @Override
635 public void onTaskRemovalStarted(int taskId) {
636 mCallback.onTaskRemovalStarted(taskId);
Andrii Kuliancf8f6832018-01-23 19:43:30 -0800637 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700638
639 @Override
640 public void onBackPressedOnTaskRoot(int taskId) {
641 mCallback.onBackPressedOnTaskRoot(taskId);
642 }
Andrii Kuliancf8f6832018-01-23 19:43:30 -0800643 }
Andrii Kuliand3134692017-06-26 14:57:02 -0700644}