diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 6dc7450ba354d..5a9dc827922fd 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -176,42 +176,6 @@ package android.app { field public static final int INVALID_STACK_ID = -1; // 0xffffffff } - public class ActivityView extends android.view.ViewGroup { - ctor public ActivityView(android.content.Context); - ctor public ActivityView(android.content.Context, android.util.AttributeSet); - ctor public ActivityView(@NonNull android.content.Context, @NonNull android.util.AttributeSet, int, boolean); - method public int getVirtualDisplayId(); - method public void onLayout(boolean, int, int, int, int); - method public void onLocationChanged(); - method public void performBackPress(); - method public void release(); - method public void setCallback(android.app.ActivityView.StateCallback); - method public void setForwardedInsets(android.graphics.Insets); - method public void startActivity(@NonNull android.content.Intent); - method public void startActivity(@NonNull android.content.Intent, android.os.UserHandle); - method public void startActivity(@NonNull android.app.PendingIntent); - method public void startActivity(@NonNull android.app.PendingIntent, @Nullable android.content.Intent, @NonNull android.app.ActivityOptions); - } - - public static final class ActivityView.Builder { - ctor public ActivityView.Builder(@NonNull android.content.Context); - method @NonNull public android.app.ActivityView build(); - method @NonNull public android.app.ActivityView.Builder setAttributeSet(@Nullable android.util.AttributeSet); - method @NonNull public android.app.ActivityView.Builder setDefaultStyle(int); - method @NonNull public android.app.ActivityView.Builder setDisableSurfaceViewBackgroundLayer(boolean); - method @NonNull public android.app.ActivityView.Builder setUsePublicVirtualDisplay(boolean); - method @NonNull public android.app.ActivityView.Builder setUseTrustedDisplay(boolean); - } - - public abstract static class ActivityView.StateCallback { - ctor public ActivityView.StateCallback(); - method public abstract void onActivityViewDestroyed(android.app.ActivityView); - method public abstract void onActivityViewReady(android.app.ActivityView); - method public void onTaskCreated(int, android.content.ComponentName); - method public void onTaskMovedToFront(int); - method public void onTaskRemovalStarted(int); - } - public class AlarmManager { method public boolean hasScheduleExactAlarm(@NonNull String, int); } diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt index 1833ed50ce4fe..5409165542f4a 100644 --- a/core/api/test-lint-baseline.txt +++ b/core/api/test-lint-baseline.txt @@ -413,8 +413,6 @@ ForbiddenSuperClass: android.app.AppDetailsActivity: -GenericException: android.app.ActivityView#finalize(): - GenericException: android.app.prediction.AppPredictor#finalize(): GenericException: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): @@ -601,20 +599,6 @@ MinMaxConstant: android.view.autofill.AutofillManager#MAX_TEMP_AUGMENTED_SERVICE -MissingGetterMatchingBuilder: android.app.ActivityView.Builder#setAttributeSet(android.util.AttributeSet): - -MissingGetterMatchingBuilder: android.app.ActivityView.Builder#setDefaultStyle(int): - -MissingGetterMatchingBuilder: android.app.ActivityView.Builder#setDisableSurfaceViewBackgroundLayer(boolean): - -MissingGetterMatchingBuilder: android.app.ActivityView.Builder#setSingleInstance(boolean): - -MissingGetterMatchingBuilder: android.app.ActivityView.Builder#setUsePublicVirtualDisplay(boolean): - -MissingGetterMatchingBuilder: android.app.ActivityView.Builder#setUseTrustedDisplay(boolean): - -MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setAttributionTag(String): - MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setFlags(int): MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setOpNames(java.util.List): @@ -791,36 +775,6 @@ MissingNullability: android.app.ActivityTaskManager#supportsMultiWindow(android. MissingNullability: android.app.ActivityTaskManager#supportsSplitScreenMultiWindow(android.content.Context) parameter #0: -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context) parameter #0: - -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet) parameter #0: - -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet) parameter #1: - -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int) parameter #0: - -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int) parameter #1: - -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int, boolean) parameter #0: - -MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int, boolean) parameter #1: - -MissingNullability: android.app.ActivityView#gatherTransparentRegion(android.graphics.Region) parameter #0: - -MissingNullability: android.app.ActivityView#onVisibilityChanged(android.view.View, int) parameter #0: - -MissingNullability: android.app.ActivityView#setCallback(android.app.ActivityView.StateCallback) parameter #0: - -MissingNullability: android.app.ActivityView#setForwardedInsets(android.graphics.Insets) parameter #0: - -MissingNullability: android.app.ActivityView#startActivity(android.content.Intent, android.os.UserHandle) parameter #1: - -MissingNullability: android.app.ActivityView.StateCallback#onActivityViewDestroyed(android.app.ActivityView) parameter #0: - -MissingNullability: android.app.ActivityView.StateCallback#onActivityViewReady(android.app.ActivityView) parameter #0: - -MissingNullability: android.app.ActivityView.StateCallback#onTaskCreated(int, android.content.ComponentName) parameter #1: - MissingNullability: android.app.AppDetailsActivity#onCreate(android.os.Bundle) parameter #0: MissingNullability: android.app.AppOpsManager#getOpStrs(): @@ -2641,8 +2595,6 @@ NoSettingsProvider: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE: -NotCloseable: android.app.ActivityView: - NotCloseable: android.app.prediction.AppPredictor: NotCloseable: android.net.EthernetManager.TetheredInterfaceRequest: @@ -2773,8 +2725,6 @@ ParcelNotFinal: android.service.autofill.InternalValidator: -ProtectedMember: android.app.ActivityView#onVisibilityChanged(android.view.View, int): - ProtectedMember: android.app.AppDetailsActivity#onCreate(android.os.Bundle): ProtectedMember: android.os.VibrationEffect#scale(int, float, int): @@ -3025,8 +2975,6 @@ UserHandle: android.telecom.TelecomManager#getDefaultDialerPackage(android.os.Us -UserHandleName: android.app.ActivityView#startActivity(android.content.Intent, android.os.UserHandle): - UserHandleName: android.content.AutofillOptions: UserHandleName: android.content.ContentCaptureOptions: diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java deleted file mode 100644 index 8c42a8a55bb10..0000000000000 --- a/core/java/android/app/ActivityView.java +++ /dev/null @@ -1,720 +0,0 @@ -/** - * Copyright (c) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.TestApi; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.LauncherApps; -import android.content.pm.ShortcutInfo; -import android.graphics.Insets; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.Region; -import android.hardware.display.VirtualDisplay; -import android.os.Bundle; -import android.os.UserHandle; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.Display; -import android.view.DisplayInfo; -import android.view.IWindow; -import android.view.IWindowManager; -import android.view.KeyEvent; -import android.view.SurfaceControl; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.window.TaskEmbedder; -import android.window.TaskOrganizerTaskEmbedder; -import android.window.VirtualDisplayTaskEmbedder; - -import dalvik.system.CloseGuard; - -/** - * Task container that allows launching activities into itself. - *

Activity launching into this container is restricted by the same rules that apply to launching - * on VirtualDisplays. - * @hide - */ -@TestApi -public class ActivityView extends ViewGroup implements android.window.TaskEmbedder.Host { - - private static final String TAG = "ActivityView"; - - private android.window.TaskEmbedder mTaskEmbedder; - - private final SurfaceView mSurfaceView; - private final SurfaceCallback mSurfaceCallback; - - private final CloseGuard mGuard = CloseGuard.get(); - private boolean mOpened; // Protected by mGuard. - - private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction(); - - // For Host - private final Point mWindowPosition = new Point(); - private final int[] mTmpArray = new int[2]; - private final Rect mTmpRect = new Rect(); - private final Matrix mScreenSurfaceMatrix = new Matrix(); - private final Region mTapExcludeRegion = new Region(); - - public ActivityView(Context context) { - this(context, null /* attrs */); - } - - public ActivityView(Context context, AttributeSet attrs) { - this(context, attrs, 0 /* defStyle */, false /* usePublicVirtualDisplay */, - false /* disableSurfaceViewBackgroundLayer */, false /* useTrustedDisplay */); - } - - /** - * This constructor let's the caller explicitly request a public virtual display as the backing - * display. Using a public display is not recommended as it exposes it to other applications, - * but it might be needed for backwards compatibility. - */ - public ActivityView( - @NonNull Context context, @NonNull AttributeSet attrs, int defStyle, - boolean usePublicVirtualDisplay) { - this(context, attrs, defStyle, usePublicVirtualDisplay, - false /* disableSurfaceViewBackgroundLayer */, false /* useTrustedDisplay */); - } - - private ActivityView( - @NonNull Context context, @NonNull AttributeSet attrs, int defStyle, - boolean usePublicVirtualDisplay, boolean disableSurfaceViewBackgroundLayer, - boolean useTrustedDisplay) { - super(context, attrs, defStyle); - if (useTaskOrganizer()) { - mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this); - } else { - mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, usePublicVirtualDisplay, - useTrustedDisplay); - } - mSurfaceView = new SurfaceView(context, null, 0, 0, disableSurfaceViewBackgroundLayer); - // Since ActivityView#getAlpha has been overridden, we should use parent class's alpha - // as authoritative to synchronize surface view's alpha value. - mSurfaceView.setAlpha(super.getAlpha()); - mSurfaceView.setUseAlpha(); - mSurfaceCallback = new SurfaceCallback(); - mSurfaceView.getHolder().addCallback(mSurfaceCallback); - addView(mSurfaceView); - - mOpened = true; - mGuard.open("release"); - } - - /** Callback that notifies when the container is ready or destroyed. */ - public abstract static class StateCallback { - - /** - * Called when the container is ready for launching activities. Calling - * {@link #startActivity(Intent)} prior to this callback will result in an - * {@link IllegalStateException}. - * - * @see #startActivity(Intent) - */ - public abstract void onActivityViewReady(ActivityView view); - - /** - * Called when the container can no longer launch activities. Calling - * {@link #startActivity(Intent)} after this callback will result in an - * {@link IllegalStateException}. - * - * @see #startActivity(Intent) - */ - public abstract void onActivityViewDestroyed(ActivityView view); - - /** - * Called when a task is created inside the container. - * This is a filtered version of {@link TaskStackListener} - */ - public void onTaskCreated(int taskId, ComponentName componentName) { } - - /** - * Called when a task visibility changes. - * @hide - */ - public void onTaskVisibilityChanged(int taskId, boolean visible) { } - - /** - * Called when a task is moved to the front of the stack inside the container. - * This is a filtered version of {@link TaskStackListener} - */ - public void onTaskMovedToFront(int taskId) { } - - /** - * Called when a task is about to be removed from the stack inside the container. - * This is a filtered version of {@link TaskStackListener} - */ - public void onTaskRemovalStarted(int taskId) { } - - /** - * Called when back is pressed on the root activity of the task. - * @hide - */ - public void onBackPressedOnTaskRoot(int taskId) { } - } - - /** - * Set the callback to be notified about state changes. - *

This class must finish initializing before {@link #startActivity(Intent)} can be called. - *

Note: If the instance was ready prior to this call being made, then - * {@link StateCallback#onActivityViewReady(ActivityView)} will be called from within - * this method call. - * - * @param callback The callback to report events to. - * - * @see StateCallback - * @see #startActivity(Intent) - */ - public void setCallback(StateCallback callback) { - if (callback == null) { - mTaskEmbedder.setListener(null); - return; - } - mTaskEmbedder.setListener(new StateCallbackAdapter(callback)); - } - - /** - * Sets the corner radius for the Activity displayed here. The corners will be - * cropped from the window painted by the contained Activity. - * - * @param cornerRadius the radius for the corners, in pixels - * @hide - */ - public void setCornerRadius(float cornerRadius) { - mSurfaceView.setCornerRadius(cornerRadius); - } - - /** - * @hide - */ - public float getCornerRadius() { - return mSurfaceView.getCornerRadius(); - } - - /** - * Control whether the surface is clipped to the same bounds as the View. If true, then - * the bounds set by {@link #setSurfaceClipBounds(Rect)} are applied to the surface as - * window-crop. - * - * @param clippingEnabled whether to enable surface clipping - * @hide - */ - public void setSurfaceClippingEnabled(boolean clippingEnabled) { - mSurfaceView.setEnableSurfaceClipping(clippingEnabled); - } - - /** - * Sets an area on the contained surface to which it will be clipped - * when it is drawn. Setting the value to null will remove the clip bounds - * and the surface will draw normally, using its full bounds. - * - * @param clipBounds The rectangular area, in the local coordinates of - * this view, to which future drawing operations will be clipped. - * @hide - */ - public void setSurfaceClipBounds(Rect clipBounds) { - mSurfaceView.setClipBounds(clipBounds); - } - - /** - * @hide - */ - public boolean getSurfaceClipBounds(Rect outRect) { - return mSurfaceView.getClipBounds(outRect); - } - - /** - * Launch an activity represented by {@link ShortcutInfo} into this container. - *

The owner of this container must be allowed to access the shortcut information, - * as defined in {@link LauncherApps#hasShortcutHostPermission()} to use this method. - *

Activity resolved by the provided {@link ShortcutInfo} must have - * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be - * launched here. Also, if activity is not owned by the owner of this container, it must allow - * embedding and the caller must have permission to embed. - *

Note: This class must finish initializing and - * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before - * this method can be called. - * - * @param shortcut the shortcut used to launch the activity. - * @param options for the activity. - * @param sourceBounds the rect containing the source bounds of the clicked icon to open - * this shortcut. - * @see StateCallback - * @see LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle) - * - * @hide - */ - public void startShortcutActivity(@NonNull ShortcutInfo shortcut, - @NonNull ActivityOptions options, @Nullable Rect sourceBounds) { - mTaskEmbedder.startShortcutActivity(shortcut, options, sourceBounds); - } - - /** - * Launch a new activity into this container. - *

Activity resolved by the provided {@link Intent} must have - * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be - * launched here. Also, if activity is not owned by the owner of this container, it must allow - * embedding and the caller must have permission to embed. - *

Note: This class must finish initializing and - * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before - * this method can be called. - * - * @param intent Intent used to launch an activity. - * - * @see StateCallback - * @see #startActivity(PendingIntent) - */ - public void startActivity(@NonNull Intent intent) { - mTaskEmbedder.startActivity(intent); - } - - /** - * Launch a new activity into this container. - *

Activity resolved by the provided {@link Intent} must have - * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be - * launched here. Also, if activity is not owned by the owner of this container, it must allow - * embedding and the caller must have permission to embed. - *

Note: This class must finish initializing and - * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before - * this method can be called. - * - * @param intent Intent used to launch an activity. - * @param user The UserHandle of the user to start this activity for. - * - * - * @see StateCallback - * @see #startActivity(PendingIntent) - */ - public void startActivity(@NonNull Intent intent, UserHandle user) { - mTaskEmbedder.startActivity(intent, user); - } - - /** - * Launch a new activity into this container. - *

Activity resolved by the provided {@link PendingIntent} must have - * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be - * launched here. Also, if activity is not owned by the owner of this container, it must allow - * embedding and the caller must have permission to embed. - *

Note: This class must finish initializing and - * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before - * this method can be called. - * - * @param pendingIntent Intent used to launch an activity. - * - * @see StateCallback - * @see #startActivity(Intent) - */ - public void startActivity(@NonNull PendingIntent pendingIntent) { - mTaskEmbedder.startActivity(pendingIntent); - } - - /** - * Launch a new activity into this container. - *

Activity resolved by the provided {@link PendingIntent} must have - * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be - * launched here. Also, if activity is not owned by the owner of this container, it must allow - * embedding and the caller must have permission to embed. - *

Note: This class must finish initializing and - * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before - * this method can be called. - * - * @param pendingIntent Intent used to launch an activity. - * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}. - * @param options options for the activity - * - * @see StateCallback - * @see #startActivity(Intent) - */ - public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent, - @NonNull ActivityOptions options) { - mTaskEmbedder.startActivity(pendingIntent, fillInIntent, options); - } - - /** - * Release this container if it is initialized. Activity launching will no longer be permitted. - */ - public void release() { - performRelease(); - } - - /** - * Triggers an update of {@link ActivityView}'s location in window to properly set tap exclude - * regions and avoid focus switches by touches on this view. - */ - public void onLocationChanged() { - mTaskEmbedder.notifyBoundsChanged(); - } - - @Override - public void onLayout(boolean changed, int l, int t, int r, int b) { - mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */); - } - - /** - * Sets the alpha value when the content of {@link SurfaceView} needs to show or hide. - *

Note: The surface view may ignore the alpha value in some cases. Refer to - * {@link SurfaceView#setAlpha} for more details. - * - * @param alpha The opacity of the view. - */ - @Override - public void setAlpha(float alpha) { - super.setAlpha(alpha); - - if (mSurfaceView != null) { - mSurfaceView.setAlpha(alpha); - } - } - - @Override - public float getAlpha() { - return mSurfaceView.getAlpha(); - } - - @Override - public boolean gatherTransparentRegion(Region region) { - return mTaskEmbedder.gatherTransparentRegion(region) - || super.gatherTransparentRegion(region); - } - - private class SurfaceCallback implements SurfaceHolder.Callback { - private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); - private final DisplayMetrics mTempMetrics = new DisplayMetrics(); - - @Override - public void surfaceCreated(SurfaceHolder surfaceHolder) { - if (!mTaskEmbedder.isInitialized()) { - initTaskEmbedder(mSurfaceView.getSurfaceControl()); - } else { - mTmpTransaction.reparent(mTaskEmbedder.getSurfaceControl(), - mSurfaceView.getSurfaceControl()).apply(); - } - mTaskEmbedder.resizeTask(getWidth(), getHeight()); - mTaskEmbedder.start(); - } - - @Override - public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) { - final Display display = getVirtualDisplay().getDisplay(); - if (!display.getDisplayInfo(mTempDisplayInfo)) { - return; - } - mTempDisplayInfo.getAppMetrics(mTempMetrics); - if (width != mTempMetrics.widthPixels || height != mTempMetrics.heightPixels) { - mTaskEmbedder.resizeTask(width, height); - mTaskEmbedder.notifyBoundsChanged(); - } - } - - @Override - public void surfaceDestroyed(SurfaceHolder surfaceHolder) { - mTaskEmbedder.stop(); - } - } - - @Override - protected void onVisibilityChanged(View changedView, int visibility) { - super.onVisibilityChanged(changedView, visibility); - mSurfaceView.setVisibility(visibility); - } - - /** - * @return the display id of the virtual display. - */ - public int getVirtualDisplayId() { - return mTaskEmbedder.getDisplayId(); - } - - /** - * @hide - * @return virtual display. - */ - public VirtualDisplay getVirtualDisplay() { - return mTaskEmbedder.getVirtualDisplay(); - } - - /** - * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the - * virtual display. - */ - public void performBackPress() { - mTaskEmbedder.performBackPress(); - } - - /** - * Initializes the task embedder. - * - * @param parent control for the surface to parent to - * @return true if the task embedder has been initialized - */ - private boolean initTaskEmbedder(SurfaceControl parent) { - if (!mTaskEmbedder.initialize(parent)) { - Log.e(TAG, "Failed to initialize ActivityView"); - return false; - } - return true; - } - - private void performRelease() { - if (!mOpened) { - return; - } - mSurfaceView.getHolder().removeCallback(mSurfaceCallback); - if (mTaskEmbedder.isInitialized()) { - mTaskEmbedder.release(); - } - mTaskEmbedder.setListener(null); - - mGuard.close(); - mOpened = false; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mGuard != null) { - mGuard.warnIfOpen(); - performRelease(); - } - } finally { - super.finalize(); - } - } - - /** - * Set forwarded insets on the virtual display. - * - * @see IWindowManager#setForwardedInsets - */ - public void setForwardedInsets(Insets insets) { - mTaskEmbedder.setForwardedInsets(insets); - } - - // Host - - /** @hide */ - @Override - public void onTaskBackgroundColorChanged(android.window.TaskEmbedder ts, int bgColor) { - if (mSurfaceView != null) { - mSurfaceView.setResizeBackgroundColor(bgColor); - } - } - - /** @hide */ - @Override - public Region getTapExcludeRegion() { - if (isAttachedToWindow() && canReceivePointerEvents()) { - Point windowPos = getPositionInWindow(); - mTapExcludeRegion.set( - windowPos.x, - windowPos.y, - windowPos.x + getWidth(), - windowPos.y + getHeight()); - // There might be views on top of us. We need to subtract those areas from the tap - // exclude region. - final ViewParent parent = getParent(); - if (parent != null) { - parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this); - } - } else { - mTapExcludeRegion.setEmpty(); - } - return mTapExcludeRegion; - } - - /** @hide */ - @Override - public Matrix getScreenToTaskMatrix() { - getLocationOnScreen(mTmpArray); - mScreenSurfaceMatrix.set(getMatrix()); - mScreenSurfaceMatrix.postTranslate(mTmpArray[0], mTmpArray[1]); - return mScreenSurfaceMatrix; - } - - /** @hide */ - @Override - public Point getPositionInWindow() { - getLocationInWindow(mTmpArray); - mWindowPosition.set(mTmpArray[0], mTmpArray[1]); - return mWindowPosition; - } - - /** @hide */ - @Override - public Rect getScreenBounds() { - getBoundsOnScreen(mTmpRect); - return mTmpRect; - } - - /** @hide */ - @Override - public IWindow getWindow() { - return super.getWindow(); - } - - /** @hide */ - @Override - public boolean canReceivePointerEvents() { - return super.canReceivePointerEvents(); - } - - /** - * Overridden by instances that require the use of the task organizer implementation instead of - * the virtual display implementation. Not for general use. - * @hide - */ - protected boolean useTaskOrganizer() { - return false; - } - - private final class StateCallbackAdapter implements TaskEmbedder.Listener { - private final StateCallback mCallback; - - private StateCallbackAdapter(ActivityView.StateCallback cb) { - mCallback = cb; - } - - @Override - public void onInitialized() { - mCallback.onActivityViewReady(ActivityView.this); - } - - @Override - public void onReleased() { - mCallback.onActivityViewDestroyed(ActivityView.this); - } - - @Override - public void onTaskCreated(int taskId, ComponentName name) { - mCallback.onTaskCreated(taskId, name); - } - - @Override - public void onTaskVisibilityChanged(int taskId, boolean visible) { - mCallback.onTaskVisibilityChanged(taskId, visible); - } - - @Override - public void onTaskMovedToFront(int taskId) { - mCallback.onTaskMovedToFront(taskId); - } - - @Override - public void onTaskRemovalStarted(int taskId) { - mCallback.onTaskRemovalStarted(taskId); - } - - @Override - public void onBackPressedOnTaskRoot(int taskId) { - mCallback.onBackPressedOnTaskRoot(taskId); - } - } - - /** The builder of {@link ActivityView} */ - public static final class Builder { - private final Context mContext; - private AttributeSet mAttrs; - private int mDefStyle; - private boolean mUsePublicVirtualDisplay; - private boolean mDisableSurfaceViewBackgroundLayer; - private boolean mUseTrustedDisplay; - - public Builder(@NonNull Context context) { - mContext = context; - mAttrs = null; - mDefStyle = 0; - mUsePublicVirtualDisplay = false; - mDisableSurfaceViewBackgroundLayer = false; - mUseTrustedDisplay = false; - } - - /** Sets {@link AttributeSet} to the {@link ActivityView}. */ - @NonNull - public Builder setAttributeSet(@Nullable AttributeSet attrs) { - mAttrs = attrs; - return this; - } - - /** - * Sets {@code defStyle} to the {@link ActivityView}. - * - * @param defaultStyle An attribute in the current theme that contains a - * reference to a style resource that supplies default values for - * the view. Can be {@code 0} to not look for defaults. - */ - @NonNull - public Builder setDefaultStyle(int defaultStyle) { - mDefStyle = defaultStyle; - return this; - } - - /** - * Sets to {@code true} to use public virtual display for the {@link ActivityView}. - *

- * Note that using a public display is not recommended as it exposes it to other - * applications, but it might be needed for backwards compatibility. - *

- */ - @NonNull - public Builder setUsePublicVirtualDisplay(boolean usePublicVirtualDisplay) { - mUsePublicVirtualDisplay = usePublicVirtualDisplay; - return this; - } - - /** - * Sets to {@code true} to disable {@link SurfaceView} background for the - * {@link ActivityView}. - */ - @NonNull - public Builder setDisableSurfaceViewBackgroundLayer( - boolean disableSurfaceViewBackgroundLayer) { - mDisableSurfaceViewBackgroundLayer = disableSurfaceViewBackgroundLayer; - return this; - } - - /** - * Sets to {@code true} to use trusted display for the {@link ActivityView}. - *

- * It enables the {@link ActivityView} to be focused without users' first touches. - *

- */ - @NonNull - public Builder setUseTrustedDisplay(boolean useTrustedDisplay) { - mUseTrustedDisplay = useTrustedDisplay; - return this; - } - - /** Creates an {@link ActivityView} */ - @NonNull - public ActivityView build() { - return new ActivityView(mContext, mAttrs, mDefStyle, - mUsePublicVirtualDisplay, mDisableSurfaceViewBackgroundLayer, - mUseTrustedDisplay); - } - } -} - diff --git a/core/java/android/window/TaskEmbedder.java b/core/java/android/window/TaskEmbedder.java deleted file mode 100644 index 0687a037df32a..0000000000000 --- a/core/java/android/window/TaskEmbedder.java +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.window; - -import static android.view.Display.INVALID_DISPLAY; - -import android.annotation.CallSuper; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.ActivityOptions; -import android.app.ActivityTaskManager; -import android.app.IActivityTaskManager; -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.LauncherApps; -import android.content.pm.ShortcutInfo; -import android.graphics.Insets; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.Region; -import android.hardware.display.VirtualDisplay; -import android.os.RemoteException; -import android.os.UserHandle; -import android.view.IWindow; -import android.view.IWindowManager; -import android.view.IWindowSession; -import android.view.KeyEvent; -import android.view.SurfaceControl; -import android.view.WindowManagerGlobal; - -import dalvik.system.CloseGuard; - -/** - * A component which handles embedded display of tasks within another window. The embedded task can - * be presented using the SurfaceControl provided from {@link #getSurfaceControl()}. - * - * @hide - */ -public abstract class TaskEmbedder { - private static final String TAG = "TaskEmbedder"; - - /** - * A component which will host the task. - */ - public interface Host { - /** @return the screen area where touches should be dispatched to the embedded Task */ - Region getTapExcludeRegion(); - - /** @return a matrix which transforms from screen-space to the embedded task surface */ - Matrix getScreenToTaskMatrix(); - - /** @return the window containing the parent surface, if attached and available */ - @Nullable IWindow getWindow(); - - /** @return the x/y offset from the origin of the window to the surface */ - Point getPositionInWindow(); - - /** @return the screen bounds of the host */ - Rect getScreenBounds(); - - /** @return whether this surface is able to receive pointer events */ - boolean canReceivePointerEvents(); - - /** @return the width of the container for the embedded task */ - int getWidth(); - - /** @return the height of the container for the embedded task */ - int getHeight(); - - /** - * Called to inform the host of the task's background color. This can be used to - * fill unpainted areas if necessary. - */ - void onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor); - - /** - * Posts a runnable to be run on the host's handler. - */ - boolean post(Runnable r); - } - - /** - * Describes changes to the state of the TaskEmbedder as well the tasks within. - */ - public interface Listener { - /** Called when the container is ready for launching activities. */ - default void onInitialized() {} - - /** Called when the container can no longer launch activities. */ - default void onReleased() {} - - /** Called when a task is created inside the container. */ - default void onTaskCreated(int taskId, ComponentName name) {} - - /** Called when a task visibility changes. */ - default void onTaskVisibilityChanged(int taskId, boolean visible) {} - - /** Called when a task is moved to the front of the stack inside the container. */ - default void onTaskMovedToFront(int taskId) {} - - /** Called when a task is about to be removed from the stack inside the container. */ - default void onTaskRemovalStarted(int taskId) {} - - /** Called when a task is created inside the container. */ - default void onBackPressedOnTaskRoot(int taskId) {} - } - - protected IActivityTaskManager mActivityTaskManager = ActivityTaskManager.getService(); - - protected final Context mContext; - protected TaskEmbedder.Host mHost; - - protected SurfaceControl.Transaction mTransaction; - protected SurfaceControl mSurfaceControl; - protected Listener mListener; - protected boolean mOpened; // Protected by mGuard. - - private final CloseGuard mGuard = CloseGuard.get(); - - - /** - * Constructs a new TaskEmbedder. - * - * @param context the context - * @param host the host for this embedded task - */ - public TaskEmbedder(Context context, TaskEmbedder.Host host) { - mContext = context; - mHost = host; - } - - /** - * Initialize this container when the ActivityView's SurfaceView is first created. - * - * @param parent the surface control for the parent surface - * @return true if initialized successfully - */ - public boolean initialize(SurfaceControl parent) { - if (isInitialized()) { - throw new IllegalStateException("Trying to initialize for the second time."); - } - - mTransaction = new SurfaceControl.Transaction(); - // Create a container surface to which the task content will be reparented - final String name = "TaskEmbedder - " + Integer.toHexString(System.identityHashCode(this)); - mSurfaceControl = new SurfaceControl.Builder() - .setContainerLayer() - .setParent(parent) - .setName(name) - .setCallsite("TaskEmbedder.initialize") - .build(); - - if (!onInitialize()) { - return false; - } - if (mListener != null && isInitialized()) { - mListener.onInitialized(); - } - mOpened = true; - mGuard.open("release"); - mTransaction.show(getSurfaceControl()).apply(); - return true; - } - - /** - * Whether this container has been initialized. - * - * @return true if initialized - */ - public abstract boolean isInitialized(); - - /** - * Called when the task embedder should be initialized. - * NOTE: all overriding methods should call this one after they finish their initialization. - * @return whether to report whether the embedder was initialized. - */ - public boolean onInitialize() { - updateLocationAndTapExcludeRegion(); - return true; - } - - /** - * Called when the task embedder should be released. - * @return whether to report whether the embedder was released. - */ - protected boolean onRelease() { - // Clear tap-exclude region (if any) for this window. - clearTapExcludeRegion(); - return true; - } - - /** - * Starts presentation of tasks in this container. - */ - public void start() { - updateLocationAndTapExcludeRegion(); - } - - /** - * Stops presentation of tasks in this container. - */ - public void stop() { - clearTapExcludeRegion(); - } - - /** - * This should be called whenever the position or size of the surface changes - * or if touchable areas above the surface are added or removed. - */ - public void notifyBoundsChanged() { - updateLocationAndTapExcludeRegion(); - } - - /** - * Called to update the dimensions whenever the host size changes. - * - * @param width the new width of the surface - * @param height the new height of the surface - */ - public void resizeTask(int width, int height) { - // Do nothing - } - - /** - * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the - * virtual display. - */ - public abstract void performBackPress(); - - /** - * An opaque unique identifier for this task surface among others being managed by the app. - */ - public abstract int getId(); - - /** - * Calculates and updates the {@param region} with the transparent region for this task - * embedder. - */ - public boolean gatherTransparentRegion(Region region) { - // Do nothing - return false; - } - - /** - * Returns the surface control for the task surface. This should be parented to a screen - * surface for display/embedding purposes. - * - * @return the surface control for the task - */ - public SurfaceControl getSurfaceControl() { - return mSurfaceControl; - } - - public int getDisplayId() { - return INVALID_DISPLAY; - } - - public VirtualDisplay getVirtualDisplay() { - return null; - } - - /** - * Set forwarded insets on the task content. - * - * @see IWindowManager#setForwardedInsets - */ - public void setForwardedInsets(Insets insets) { - // Do nothing - } - - /** - * Updates position and bounds information needed by WM and IME to manage window - * focus and touch events properly. - *

- * This should be called whenever the position or size of the surface changes - * or if touchable areas above the surface are added or removed. - */ - protected void updateLocationAndTapExcludeRegion() { - if (!isInitialized() || mHost.getWindow() == null) { - return; - } - applyTapExcludeRegion(mHost.getWindow(), mHost.getTapExcludeRegion()); - } - - /** - * Call to update the tap exclude region for the window. - *

- * This should not normally be called directly, but through - * {@link #updateLocationAndTapExcludeRegion()}. This method - * is provided as an optimization when managing multiple TaskSurfaces within a view. - * - * @see IWindowSession#updateTapExcludeRegion(IWindow, Region) - */ - private void applyTapExcludeRegion(IWindow window, @Nullable Region tapExcludeRegion) { - try { - IWindowSession session = WindowManagerGlobal.getWindowSession(); - session.updateTapExcludeRegion(window, tapExcludeRegion); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } - - /** - * Removes the tap exclude region set by {@link #updateLocationAndTapExcludeRegion()}. - */ - private void clearTapExcludeRegion() { - if (!isInitialized() || mHost.getWindow() == null) { - return; - } - applyTapExcludeRegion(mHost.getWindow(), null); - } - - /** - * Set the callback to be notified about state changes. - *

This class must finish initializing before {@link #startActivity(Intent)} can be called. - *

Note: If the instance was ready prior to this call being made, then - * {@link Listener#onInitialized()} will be called from within this method call. - * - * @param listener The listener to report events to. - * - * @see ActivityView.StateCallback - * @see #startActivity(Intent) - */ - public void setListener(TaskEmbedder.Listener listener) { - mListener = listener; - if (mListener != null && isInitialized()) { - mListener.onInitialized(); - } - } - - /** - * Launch a new activity into this container. - * - * @param intent Intent used to launch an activity - * - * @see #startActivity(PendingIntent) - */ - public void startActivity(@NonNull Intent intent) { - final ActivityOptions options = prepareActivityOptions(null); - mContext.startActivity(intent, options.toBundle()); - } - - /** - * Launch a new activity into this container. - * - * @param intent Intent used to launch an activity - * @param user The UserHandle of the user to start this activity for - * - * @see #startActivity(PendingIntent) - */ - public void startActivity(@NonNull Intent intent, UserHandle user) { - final ActivityOptions options = prepareActivityOptions(null); - mContext.startActivityAsUser(intent, options.toBundle(), user); - } - - /** - * Launch a new activity into this container. - * - * @param pendingIntent Intent used to launch an activity - * - * @see #startActivity(Intent) - */ - public void startActivity(@NonNull PendingIntent pendingIntent) { - final ActivityOptions options = prepareActivityOptions(null); - try { - pendingIntent.send(null /* context */, 0 /* code */, null /* intent */, - null /* onFinished */, null /* handler */, null /* requiredPermission */, - options.toBundle()); - } catch (PendingIntent.CanceledException e) { - throw new RuntimeException(e); - } - } - - /** - * Launch a new activity into this container. - * - * @param pendingIntent Intent used to launch an activity - * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()} - * @param options options for the activity - * - * @see #startActivity(Intent) - */ - public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent, - @NonNull ActivityOptions options) { - prepareActivityOptions(options); - try { - pendingIntent.send(mContext, 0 /* code */, fillInIntent, - null /* onFinished */, null /* handler */, null /* requiredPermission */, - options.toBundle()); - } catch (PendingIntent.CanceledException e) { - throw new RuntimeException(e); - } - } - - /** - * Launch an activity represented by {@link ShortcutInfo} into this container. - *

The owner of this container must be allowed to access the shortcut information, - * as defined in {@link LauncherApps#hasShortcutHostPermission()} to use this method. - * - * @param shortcut the shortcut used to launch the activity. - * @param options options for the activity. - * @param sourceBounds the rect containing the source bounds of the clicked icon to open - * this shortcut. - * - * @see #startActivity(Intent) - */ - public void startShortcutActivity(@NonNull ShortcutInfo shortcut, - @NonNull ActivityOptions options, @Nullable Rect sourceBounds) { - LauncherApps service = - (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE); - prepareActivityOptions(options); - service.startShortcut(shortcut, sourceBounds, options.toBundle()); - } - - /** - * Check if container is ready to launch and modify {@param options} to target the virtual - * display, creating them if necessary. - */ - @CallSuper - protected ActivityOptions prepareActivityOptions(ActivityOptions options) { - if (!isInitialized()) { - throw new IllegalStateException( - "Trying to start activity before ActivityView is ready."); - } - if (options == null) { - options = ActivityOptions.makeBasic(); - } - return options; - } - - /** - * Releases the resources for this TaskEmbedder. Tasks will no longer be launchable - * within this container. - * - *

Note: Calling this method is allowed after {@link Listener#onInitialized()} callback is - * triggered and before {@link Listener#onReleased()}. - */ - public void release() { - if (!isInitialized()) { - throw new IllegalStateException("Trying to release container that is not initialized."); - } - performRelease(); - } - - private boolean performRelease() { - if (!mOpened) { - return false; - } - - mTransaction.reparent(mSurfaceControl, null).apply(); - mSurfaceControl.release(); - - boolean reportReleased = onRelease(); - if (mListener != null && reportReleased) { - mListener.onReleased(); - } - mOpened = false; - mGuard.close(); - return true; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mGuard != null) { - mGuard.warnIfOpen(); - performRelease(); - } - } finally { - super.finalize(); - } - } -} diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java deleted file mode 100644 index 1e293df38cf82..0000000000000 --- a/core/java/android/window/TaskOrganizerTaskEmbedder.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.window; - -import static android.app.ActivityTaskManager.INVALID_TASK_ID; -import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; - -import android.app.ActivityManager; -import android.app.ActivityOptions; -import android.content.Context; -import android.graphics.Rect; -import android.util.Log; -import android.view.KeyEvent; -import android.view.SurfaceControl; - -/** - * A component which handles embedded display of tasks within another window. The embedded task can - * be presented using the SurfaceControl provided from {@link #getSurfaceControl()}. - * - * @hide - */ -public class TaskOrganizerTaskEmbedder extends TaskEmbedder { - private static final String TAG = "TaskOrgTaskEmbedder"; - private static final boolean DEBUG = false; - - private TaskOrganizer mTaskOrganizer; - private ActivityManager.RunningTaskInfo mTaskInfo; - private WindowContainerToken mTaskToken; - private SurfaceControl mTaskLeash; - private boolean mPendingNotifyBoundsChanged; - - /** - * Constructs a new TaskEmbedder. - * - * @param context the context - * @param host the host for this embedded task - */ - public TaskOrganizerTaskEmbedder(Context context, TaskOrganizerTaskEmbedder.Host host) { - super(context, host); - } - - /** - * Whether this container has been initialized. - * - * @return true if initialized - */ - @Override - public boolean isInitialized() { - return mTaskOrganizer != null; - } - - @Override - public boolean onInitialize() { - if (DEBUG) { - log("onInitialize"); - } - // Register the task organizer - mTaskOrganizer = new TaskOrganizerImpl(); - // TODO(wm-shell): This currently prevents other organizers from controlling MULT_WINDOW - // windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that - // infrastructure is ready. - // mTaskOrganizer.registerOrganizer(); - // mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true); - - return super.onInitialize(); - } - - @Override - protected boolean onRelease() { - if (DEBUG) { - log("onRelease"); - } - if (!isInitialized()) { - return false; - } - mTaskOrganizer.unregisterOrganizer(); - resetTaskInfo(); - return true; - } - - /** - * Starts presentation of tasks in this container. - */ - @Override - public void start() { - super.start(); - if (DEBUG) { - log("start"); - } - if (!isInitialized()) { - return; - } - if (mTaskToken == null) { - return; - } - WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setHidden(mTaskToken, false /* hidden */); - mTaskOrganizer.applyTransaction(wct); - // TODO(b/151449487): Only call callback once we enable synchronization - if (mListener != null) { - mListener.onTaskVisibilityChanged(getTaskId(), true); - } - } - - /** - * Stops presentation of tasks in this container. - */ - @Override - public void stop() { - super.stop(); - if (DEBUG) { - log("stop"); - } - if (!isInitialized()) { - return; - } - if (mTaskToken == null) { - return; - } - WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setHidden(mTaskToken, true /* hidden */); - mTaskOrganizer.applyTransaction(wct); - // TODO(b/151449487): Only call callback once we enable synchronization - if (mListener != null) { - mListener.onTaskVisibilityChanged(getTaskId(), false); - } - } - - /** - * This should be called whenever the position or size of the surface changes - * or if touchable areas above the surface are added or removed. - */ - @Override - public void notifyBoundsChanged() { - super.notifyBoundsChanged(); - if (DEBUG) { - log("notifyBoundsChanged: screenBounds=" + mHost.getScreenBounds()); - } - if (mTaskToken == null) { - mPendingNotifyBoundsChanged = true; - return; - } - mPendingNotifyBoundsChanged = false; - - // Update based on the screen bounds - Rect screenBounds = mHost.getScreenBounds(); - if (screenBounds.left < 0 || screenBounds.top < 0) { - screenBounds.offsetTo(0, 0); - } - - WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setBounds(mTaskToken, screenBounds); - // TODO(b/151449487): Enable synchronization - mTaskOrganizer.applyTransaction(wct); - } - - /** - * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the - * virtual display. - */ - @Override - public void performBackPress() { - // Do nothing, the task org task should already have focus if the caller is not focused - return; - } - - /** An opaque unique identifier for this task surface among others being managed by the app. */ - @Override - public int getId() { - return getTaskId(); - } - - /** - * Check if container is ready to launch and create {@link ActivityOptions} to target the - * virtual display. - * @param options The existing options to amend, or null if the caller wants new options to be - * created - */ - @Override - protected ActivityOptions prepareActivityOptions(ActivityOptions options) { - options = super.prepareActivityOptions(options); - options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW); - return options; - } - - private int getTaskId() { - return mTaskInfo != null - ? mTaskInfo.taskId - : INVALID_TASK_ID; - } - - private void resetTaskInfo() { - if (DEBUG) { - log("resetTaskInfo"); - } - mTaskInfo = null; - mTaskToken = null; - mTaskLeash = null; - } - - private void log(String msg) { - Log.d(TAG, "[" + System.identityHashCode(this) + "] " + msg); - } - - private class TaskOrganizerImpl extends TaskOrganizer { - @Override - public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { - if (DEBUG) { - log("taskAppeared: " + taskInfo.taskId); - } - - mTaskInfo = taskInfo; - mTaskToken = taskInfo.token; - mTaskLeash = leash; - mTransaction.reparent(mTaskLeash, mSurfaceControl) - .show(mTaskLeash) - .show(mSurfaceControl) - .apply(); - if (mPendingNotifyBoundsChanged) { - // TODO: Either defer show or hide and synchronize show with the resize - notifyBoundsChanged(); - } - mHost.post(() -> mHost.onTaskBackgroundColorChanged(TaskOrganizerTaskEmbedder.this, - taskInfo.taskDescription.getBackgroundColor())); - - if (mListener != null) { - mListener.onTaskCreated(taskInfo.taskId, taskInfo.baseActivity); - } - } - - @Override - public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { - mTaskInfo.taskDescription = taskInfo.taskDescription; - mHost.post(() -> mHost.onTaskBackgroundColorChanged(TaskOrganizerTaskEmbedder.this, - taskInfo.taskDescription.getBackgroundColor())); - } - - @Override - public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { - if (DEBUG) { - log("taskVanished: " + taskInfo.taskId); - } - - if (mTaskToken != null && (taskInfo == null - || mTaskToken.asBinder().equals(taskInfo.token.asBinder()))) { - if (mListener != null) { - mListener.onTaskRemovalStarted(taskInfo.taskId); - } - resetTaskInfo(); - } - } - - @Override - public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) { - if (mListener != null) { - mListener.onBackPressedOnTaskRoot(taskInfo.taskId); - } - } - } -} diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java deleted file mode 100644 index be5d55af5e8a4..0000000000000 --- a/core/java/android/window/VirtualDisplayTaskEmbedder.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.window; - -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; -import static android.view.Display.INVALID_DISPLAY; - -import android.app.ActivityManager; -import android.app.ActivityOptions; -import android.app.ActivityTaskManager; -import android.app.ActivityTaskManager.RootTaskInfo; -import android.app.ActivityView; -import android.app.TaskStackListener; -import android.content.ComponentName; -import android.content.Context; -import android.graphics.Insets; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Region; -import android.hardware.display.DisplayManager; -import android.hardware.display.VirtualDisplay; -import android.hardware.input.InputManager; -import android.os.RemoteException; -import android.os.SystemClock; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.IWindowManager; -import android.view.IWindowSession; -import android.view.InputDevice; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.WindowManagerGlobal; -import android.view.inputmethod.InputMethodManager; - -import java.util.List; - -/** - * A component which handles embedded display of tasks within another window. The embedded task can - * be presented using the SurfaceControl provided from {@link #getSurfaceControl()}. - * - * @hide - */ -public class VirtualDisplayTaskEmbedder extends TaskEmbedder { - private static final String TAG = "VirDispTaskEmbedder"; - private static final String DISPLAY_NAME = "TaskVirtualDisplay"; - - // For Virtual Displays - private int mDisplayDensityDpi; - private final boolean mUsePublicVirtualDisplay; - private final boolean mUseTrustedDisplay; - private VirtualDisplay mVirtualDisplay; - private Insets mForwardedInsets; - private TaskStackListener mTaskStackListener; - - /** - * Constructs a new TaskEmbedder. - * - * @param context the context - * @param host the host for this embedded task - */ - public VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host, - boolean usePublicVirtualDisplay, boolean useTrustedDisplay) { - super(context, host); - mUsePublicVirtualDisplay = usePublicVirtualDisplay; - mUseTrustedDisplay = useTrustedDisplay; - } - - /** - * Whether this container has been initialized. - * - * @return true if initialized - */ - @Override - public boolean isInitialized() { - return mVirtualDisplay != null; - } - - @Override - public boolean onInitialize() { - final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); - mDisplayDensityDpi = getBaseDisplayDensity(); - - int virtualDisplayFlags = VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY - | VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL; - if (mUsePublicVirtualDisplay) { - virtualDisplayFlags |= VIRTUAL_DISPLAY_FLAG_PUBLIC; - } - if (mUseTrustedDisplay) { - virtualDisplayFlags |= VIRTUAL_DISPLAY_FLAG_TRUSTED; - } - - mVirtualDisplay = displayManager.createVirtualDisplay( - DISPLAY_NAME + "@" + System.identityHashCode(this), mHost.getWidth(), - mHost.getHeight(), mDisplayDensityDpi, null, virtualDisplayFlags); - - if (mVirtualDisplay == null) { - Log.e(TAG, "Failed to initialize TaskEmbedder"); - return false; - } - - try { - // TODO: Find a way to consolidate these calls to the server. - final int displayId = getDisplayId(); - final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - WindowManagerGlobal.getWindowSession().reparentDisplayContent( - mHost.getWindow(), mSurfaceControl, displayId); - wm.dontOverrideDisplayInfo(displayId); - setForwardedInsets(mForwardedInsets); - - mTaskStackListener = new TaskStackListenerImpl(); - mActivityTaskManager.registerTaskStackListener(mTaskStackListener); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - - return super.onInitialize(); - } - - @Override - protected boolean onRelease() { - super.onRelease(); - // Clear activity view geometry for IME on this display - clearActivityViewGeometryForIme(); - - if (mTaskStackListener != null) { - try { - mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); - } catch (RemoteException e) { - Log.e(TAG, "Failed to unregister task stack listener", e); - } - mTaskStackListener = null; - } - - if (isInitialized()) { - mVirtualDisplay.release(); - mVirtualDisplay = null; - return true; - } - return false; - } - - /** - * Starts presentation of tasks in this container. - */ - @Override - public void start() { - super.start(); - if (isInitialized()) { - mVirtualDisplay.setDisplayState(true); - } - } - - /** - * Stops presentation of tasks in this container. - */ - @Override - public void stop() { - super.stop(); - if (isInitialized()) { - mVirtualDisplay.setDisplayState(false); - clearActivityViewGeometryForIme(); - } - } - - /** - * Called to update the dimensions whenever the host size changes. - * - * @param width the new width of the surface - * @param height the new height of the surface - */ - @Override - public void resizeTask(int width, int height) { - mDisplayDensityDpi = getBaseDisplayDensity(); - if (isInitialized()) { - mVirtualDisplay.resize(width, height, mDisplayDensityDpi); - } - } - - /** - * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the - * virtual display. - */ - @Override - public void performBackPress() { - if (!isInitialized()) { - return; - } - final int displayId = mVirtualDisplay.getDisplay().getDisplayId(); - final InputManager im = InputManager.getInstance(); - im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, displayId), - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); - im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, displayId), - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); - } - - @Override - public boolean gatherTransparentRegion(Region region) { - // The tap exclude region may be affected by any view on top of it, so we detect the - // possible change by monitoring this function. The tap exclude region is only used - // for virtual displays. - notifyBoundsChanged(); - return super.gatherTransparentRegion(region); - } - - /** An opaque unique identifier for this task surface among others being managed by the app. */ - @Override - public int getId() { - return getDisplayId(); - } - - @Override - public int getDisplayId() { - if (isInitialized()) { - return mVirtualDisplay.getDisplay().getDisplayId(); - } - return INVALID_DISPLAY; - } - - @Override - public VirtualDisplay getVirtualDisplay() { - if (isInitialized()) { - return mVirtualDisplay; - } - return null; - } - - /** - * Check if container is ready to launch and create {@link ActivityOptions} to target the - * virtual display. - * @param options The existing options to amend, or null if the caller wants new options to be - * created - */ - @Override - protected ActivityOptions prepareActivityOptions(ActivityOptions options) { - options = super.prepareActivityOptions(options); - options.setLaunchDisplayId(getDisplayId()); - return options; - } - - /** - * Set forwarded insets on the virtual display. - * - * @see IWindowManager#setForwardedInsets - */ - @Override - public void setForwardedInsets(Insets insets) { - mForwardedInsets = insets; - if (!isInitialized()) { - return; - } - try { - final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - wm.setForwardedInsets(getDisplayId(), mForwardedInsets); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } - - /** - * Updates position and bounds information needed by WM and IME to manage window - * focus and touch events properly. - *

- * This should be called whenever the position or size of the surface changes - * or if touchable areas above the surface are added or removed. - */ - @Override - protected void updateLocationAndTapExcludeRegion() { - super.updateLocationAndTapExcludeRegion(); - if (!isInitialized() || mHost.getWindow() == null) { - return; - } - reportLocation(mHost.getScreenToTaskMatrix(), mHost.getPositionInWindow()); - } - - /** - * Call to update the position and transform matrix for the embedded surface. - *

- * This should not normally be called directly, but through - * {@link #updateLocationAndTapExcludeRegion()}. This method - * is provided as an optimization when managing multiple TaskSurfaces within a view. - * - * @param screenToViewMatrix the matrix/transform from screen space to view space - * @param positionInWindow the window-relative position of the surface - * - * @see InputMethodManager#reportActivityView(int, Matrix) - */ - private void reportLocation(Matrix screenToViewMatrix, Point positionInWindow) { - try { - final int displayId = getDisplayId(); - mContext.getSystemService(InputMethodManager.class) - .reportActivityView(displayId, screenToViewMatrix); - IWindowSession session = WindowManagerGlobal.getWindowSession(); - session.updateDisplayContentLocation(mHost.getWindow(), positionInWindow.x, - positionInWindow.y, displayId); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } - - /** - * @see InputMethodManager#reportActivityView(int, Matrix) - */ - private void clearActivityViewGeometryForIme() { - final int displayId = getDisplayId(); - mContext.getSystemService(InputMethodManager.class).reportActivityView(displayId, null); - } - - private static KeyEvent createKeyEvent(int action, int code, int displayId) { - long when = SystemClock.uptimeMillis(); - final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */, - 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */, - KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, - InputDevice.SOURCE_KEYBOARD); - ev.setDisplayId(displayId); - return ev; - } - - /** Get density of the hosting display. */ - private int getBaseDisplayDensity() { - return mContext.getResources().getConfiguration().densityDpi; - } - - /** - * A task change listener that detects background color change of the topmost stack on our - * virtual display and updates the background of the surface view. This background will be shown - * when surface view is resized, but the app hasn't drawn its content in new size yet. - * It also calls StateCallback.onTaskMovedToFront to notify interested parties that the stack - * associated with the {@link ActivityView} has had a Task moved to the front. This is useful - * when needing to also bring the host Activity to the foreground at the same time. - */ - private class TaskStackListenerImpl extends TaskStackListener { - - @Override - public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo runningTaskInfo) - throws RemoteException { - if (!isInitialized()) { - return; - } - if (runningTaskInfo.displayId != getDisplayId()) { - return; - } - RootTaskInfo taskInfo = getTopMostRootTaskInfo(); - if (taskInfo == null) { - return; - } - // Found the topmost stack on target display. Now check if the topmost task's - // description changed. - if (runningTaskInfo.taskId == taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]) { - mHost.post(()-> mHost.onTaskBackgroundColorChanged(VirtualDisplayTaskEmbedder.this, - runningTaskInfo.taskDescription.getBackgroundColor())); - } - } - - @Override - public void onTaskMovedToFront(ActivityManager.RunningTaskInfo runningTaskInfo) - throws RemoteException { - if (!isInitialized() || mListener == null - || runningTaskInfo.displayId != getDisplayId()) { - return; - } - - RootTaskInfo taskInfo = getTopMostRootTaskInfo(); - // if TaskInfo was null or unrelated to the "move to front" then there's no use - // notifying the callback - if (taskInfo != null && runningTaskInfo.taskId == taskInfo.childTaskIds[ - taskInfo.childTaskIds.length - 1]) { - mListener.onTaskMovedToFront(runningTaskInfo.taskId); - } - } - - @Override - public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException { - if (mListener == null || !isInitialized()) { - return; - } - - RootTaskInfo taskInfo = getTopMostRootTaskInfo(); - // if TaskInfo was null or unrelated to the task creation then there's no use - // notifying the callback - if (taskInfo != null - && taskId == taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]) { - mListener.onTaskCreated(taskId, componentName); - } - } - - @Override - public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo) - throws RemoteException { - if (mListener == null || !isInitialized() - || taskInfo.displayId != getDisplayId()) { - return; - } - - mListener.onTaskRemovalStarted(taskInfo.taskId); - } - - private RootTaskInfo getTopMostRootTaskInfo() throws RemoteException { - // Find the topmost task on our virtual display - it will define the background - // color of the surface view during resizing. - final int displayId = getDisplayId(); - final List taskInfoList = - mActivityTaskManager.getAllRootTaskInfosOnDisplay(displayId); - if (taskInfoList.isEmpty()) { - return null; - } - return taskInfoList.get(0); - } - } -}