Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdfddd3f authored by Antonio Kantek's avatar Antonio Kantek Committed by Automerger Merge Worker
Browse files

Merge "Deleting ActivityView" into sc-dev am: b1c5d7fa

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14430990

Change-Id: Ibf78e9566b329920e0e89ea57d9c011362848d50
parents 6ee7c7d9 b1c5d7fa
Loading
Loading
Loading
Loading
+0 −36
Original line number Diff line number Diff line
@@ -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);
  }
+0 −52
Original line number Diff line number Diff line
@@ -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<java.lang.String>):
@@ -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:
+0 −720

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −490
Original line number Diff line number Diff line
/*
 * 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.
     * <p>
     * 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.
     * <p>
     * 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.
     * <p>This class must finish initializing before {@link #startActivity(Intent)} can be called.
     * <p>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.
     * <p>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.
     *
     * <p>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();
        }
    }
}
+0 −274

File deleted.

Preview size limit exceeded, changes collapsed.

Loading