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

Commit 4341e620 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/32753793',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/32753793', 'googleplex-android-review.googlesource.com/32754356', 'googleplex-android-review.googlesource.com/32627908'] into 25Q2-release.

Change-Id: I4f68886629a85d4c404dfc7e276b1ab2363c50b4
parents 4e4f9369 99a4bd6c
Loading
Loading
Loading
Loading
+133 −25
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.service.dreams.Flags.dreamHandlesBeingObscured;
import static android.service.dreams.Flags.dreamHandlesConfirmKeys;
import static android.service.dreams.Flags.startAndStopDozingInBackground;

import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.IdRes;
import android.annotation.IntDef;
@@ -254,7 +255,6 @@ public class DreamService extends Service implements Window.Callback {
            "android.service.dream.DreamService.dream_overlay_component";

    private final IDreamManager mDreamManager;
    private final Handler mHandler;
    private IBinder mDreamToken;
    private Window mWindow;
    private Activity mActivity;
@@ -323,19 +323,87 @@ public class DreamService extends Service implements Window.Callback {
        /** Returns the associated service info */
        ServiceInfo getServiceInfo();

        /** Returns the handler to be used for any posted operation */
        Handler getHandler();

        /** Returns the package manager */
        PackageManager getPackageManager();

        /** Returns the resources */
        Resources getResources();

        /** Returns a specialized handler to ensure Runnables are not suspended */
        WakefulHandler getWakefulHandler();
    }

    /**
     * {@link WakefulHandler} is an interface for defining an object that helps post work without
     * being interrupted by doze state.
     *
     * @hide
     */
    public interface WakefulHandler {
        /** Posts a {@link Runnable} to be ran on the underlying {@link Handler}. */
        void post(Runnable r);

        /**
         * Returns the underlying {@link Handler}. Should only be used for passing the handler into
         * a function and not for directly calling methods on it.
         */
        Handler getHandler();
    }

    /**
     * {@link WakefulHandlerImpl} ensures work on a handler is not suspended by wrapping the call
     * with a partial wakelock. Note that this is only needed for Doze DreamService implementations.
     * In this case, the component should have wake lock permissions. When such permission is not
     * available, this class behaves like an ordinary handler.
     */
    private static final class WakefulHandlerImpl implements WakefulHandler {
        private static final String SERVICE_HANDLER_WAKE_LOCK_TAG = "dream:service:handler";
        private Context mContext;
        private Handler mHandler;

        private PowerManager.WakeLock mWakeLock;

        private PowerManager.WakeLock getWakeLock() {
            if (mContext.checkCallingOrSelfPermission(Manifest.permission.WAKE_LOCK)
                    != PERMISSION_GRANTED) {
                return null;
            }

            final PowerManager powerManager = mContext.getSystemService(PowerManager.class);

            if (powerManager == null) {
                return null;
            }

            return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    SERVICE_HANDLER_WAKE_LOCK_TAG);
        }

        WakefulHandlerImpl(Context context) {
            mContext = context;
            mHandler = new Handler(Looper.getMainLooper());
            mWakeLock = getWakeLock();
        }

        @Override
        public void post(Runnable r) {
            if (mWakeLock != null) {
                mHandler.post(mWakeLock.wrap(r));
            } else {
                mHandler.post(r);
            }
        }

        @Override
        public Handler getHandler() {
            return mHandler;
        }
    }

    private static final class DefaultInjector implements Injector {
        private Context mContext;
        private Class<?> mClassName;
        private WakefulHandler mWakefulHandler;

        public void init(Context context) {
            mContext = context;
@@ -346,8 +414,6 @@ public class DreamService extends Service implements Window.Callback {
        public DreamOverlayConnectionHandler createOverlayConnection(
                ComponentName overlayComponent,
                Runnable onDisconnected) {
            final Resources resources = mContext.getResources();

            return new DreamOverlayConnectionHandler(
                    /* context= */ mContext,
                    Looper.getMainLooper(),
@@ -381,8 +447,14 @@ public class DreamService extends Service implements Window.Callback {
        }

        @Override
        public Handler getHandler() {
            return new Handler(Looper.getMainLooper());
        public WakefulHandler getWakefulHandler() {
            synchronized (this) {
                if (mWakefulHandler == null) {
                    mWakefulHandler = new WakefulHandlerImpl(mContext);
                }
            }

            return mWakefulHandler;
        }

        @Override
@@ -394,7 +466,6 @@ public class DreamService extends Service implements Window.Callback {
        public Resources getResources() {
            return mContext.getResources();
        }

    }

    public DreamService() {
@@ -412,7 +483,6 @@ public class DreamService extends Service implements Window.Callback {
        mInjector = injector;
        mInjector.init(this);
        mDreamManager = mInjector.getDreamManager();
        mHandler = mInjector.getHandler();
    }

    /**
@@ -925,11 +995,17 @@ public class DreamService extends Service implements Window.Callback {
        }
    }

    private void post(Runnable runnable) {
        // The handler is based on the populated context is not ready at construction time.
        // therefore we fetch on demand.
        mInjector.getWakefulHandler().post(runnable);
    }

    /**
     * Updates doze state. Note that this must be called on the mHandler.
     */
    private void updateDoze() {
        mHandler.post(() -> {
        post(() -> {
            if (mDreamToken == null) {
                Slog.w(mTag, "Updating doze without a dream token.");
                return;
@@ -971,7 +1047,7 @@ public class DreamService extends Service implements Window.Callback {
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public void stopDozing() {
        mHandler.post(() -> {
        post(() -> {
            if (mDreamToken == null) {
                return;
            }
@@ -1211,13 +1287,23 @@ public class DreamService extends Service implements Window.Callback {
        mOverlayCallback = new IDreamOverlayCallback.Stub() {
            @Override
            public void onExitRequested() {
                final long token = Binder.clearCallingIdentity();
                try {
                    // Simply finish dream when exit is requested.
                mHandler.post(() -> finishInternal());
                    post(() -> finishInternal());
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }

            @Override
            public void onRedirectWake(boolean redirect) {
                final long token = Binder.clearCallingIdentity();
                try {
                    mRedirectWake = redirect;
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        };

@@ -1310,7 +1396,7 @@ public class DreamService extends Service implements Window.Callback {
     * </p>
     */
    public final void finish() {
        mHandler.post(this::finishInternal);
        post(this::finishInternal);
    }

    private void finishInternal() {
@@ -1372,7 +1458,7 @@ public class DreamService extends Service implements Window.Callback {
     * </p>
     */
    public final void wakeUp() {
        mHandler.post(()-> wakeUp(false));
        post(()-> wakeUp(false));
    }

    /**
@@ -1821,7 +1907,8 @@ public class DreamService extends Service implements Window.Callback {

    @Override
    protected void dump(final FileDescriptor fd, PrintWriter pw, final String[] args) {
        DumpUtils.dumpAsync(mHandler, (pw1, prefix) -> dumpOnHandler(fd, pw1, args), pw, "", 1000);
        DumpUtils.dumpAsync(mInjector.getWakefulHandler().getHandler(),
                (pw1, prefix) -> dumpOnHandler(fd, pw1, args), pw, "", 1000);
    }

    /** @hide */
@@ -1877,31 +1964,52 @@ public class DreamService extends Service implements Window.Callback {
                return;
            }

            service.mHandler.post(() -> consumer.accept(service));
            service.post(() -> consumer.accept(service));
        }

        @Override
        public void attach(final IBinder dreamToken, final boolean canDoze,
                final boolean isPreviewMode, IRemoteCallback started) {
            post(dreamService -> dreamService.attach(dreamToken, canDoze, isPreviewMode, started));
            final long token = Binder.clearCallingIdentity();
            try {
                post(dreamService -> dreamService.attach(dreamToken, canDoze, isPreviewMode,
                        started));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void detach() {
            final long token = Binder.clearCallingIdentity();
            try {
                post(DreamService::detach);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void wakeUp() {
            final long token = Binder.clearCallingIdentity();
            try {
                post(dreamService -> dreamService.wakeUp(true /*fromSystem*/));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void comeToFront() {
            final long token = Binder.clearCallingIdentity();
            try {
                if (!dreamHandlesBeingObscured()) {
                    return;
                }
                post(DreamService::comeToFront);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }

+0 −2
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.graphics.Rect;
import android.view.InsetsState;
import android.view.ISurfaceControlViewHostParent;
import android.window.ISurfaceSyncGroup;
import android.window.InputTransferToken;

/**
 * API from content embedder back to embedded content in SurfaceControlViewHost
@@ -33,7 +32,6 @@ interface ISurfaceControlViewHost {
     * APIs that are blocking
     */
    oneway void onConfigurationChanged(in Configuration newConfig);
    oneway void onDispatchAttachedToWindow(in InputTransferToken token);
    oneway void onDispatchDetachedFromWindow();
    oneway void onInsetsChanged(in InsetsState state, in Rect insetFrame);
    ISurfaceSyncGroup getSurfaceSyncGroup();
+2 −3
Original line number Diff line number Diff line
@@ -313,9 +313,8 @@ interface IWindowSession {
    /**
     * Update the flags on an input channel associated with a particular surface.
     */
    oneway void updateInputChannel(in IBinder channelToken,
            in @nullable InputTransferToken hostInputTransferToken,
            int displayId, in SurfaceControl surface, int flags, int privateFlags, int inputFeatures,
    oneway void updateInputChannel(in IBinder channelToken, int displayId,
            in SurfaceControl surface, int flags, int privateFlags, int inputFeatures,
            in Region region);

    /**
+0 −14
Original line number Diff line number Diff line
@@ -78,20 +78,6 @@ public class SurfaceControlViewHost {
            });
        }

        @Override
        public void onDispatchAttachedToWindow(InputTransferToken hostInputTransferToken) {
            boolean hostInputTransferTokenChanged =
                    !Objects.equals(hostInputTransferToken, mWm.mHostInputTransferToken);
            if (!hostInputTransferTokenChanged) {
                return;
            }

            mWm.setHostInputTransferToken(hostInputTransferToken);
            if (mViewRoot != null && mViewRoot.mView != null) {
                mWm.updateInputChannel(getWindowToken().asBinder());
            }
        }

        @Override
        public void onDispatchDetachedFromWindow() {
            if (mViewRoot == null) {
+1 −33
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.view;


import static android.view.flags.Flags.FLAG_DEPRECATE_SURFACE_VIEW_Z_ORDER_APIS;
import static android.view.flags.Flags.FLAG_SURFACE_VIEW_GET_SURFACE_PACKAGE;
import static android.view.flags.Flags.FLAG_SURFACE_VIEW_SET_COMPOSITION_ORDER;
@@ -24,8 +23,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
import static android.view.flags.Flags.FLAG_SURFACE_VIEW_GET_SURFACE_PACKAGE;
import static android.view.flags.Flags.FLAG_SURFACE_VIEW_SET_COMPOSITION_ORDER;

import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
@@ -62,7 +59,6 @@ import android.util.Log;
import android.view.SurfaceControl.Transaction;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
import android.window.InputTransferToken;
import android.window.SurfaceSyncGroup;

import com.android.graphics.hwui.flags.Flags;
@@ -351,7 +347,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                    sv.mSurfacePackage.getRemoteInterface().attachParentInterface(this);
                    mSurfaceView = sv;
                } catch (RemoteException e) {
                    Log.d(TAG, "Failed to attach parent interface to SCVH. Likely SCVH is already "
                    Log.d(TAG, "Failed to attach parent interface to SCVH. Likely SCVH is alraedy "
                            + "dead.");
                }
            }
@@ -496,37 +492,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        mTag = "SV[" + System.identityHashCode(this) + windowName + "]";
    }

    private void dispatchScvhAttachedToHost() {
        final ViewRootImpl viewRoot = getViewRootImpl();
        if (viewRoot == null) {
            return;
        }

        IBinder inputToken = viewRoot.getInputToken();
        if (inputToken == null) {
            // We don't have an input channel so we can't transfer focus or active
            // touch gestures to embedded.
            return;
        }

        try {
            mSurfacePackage
                    .getRemoteInterface()
                    .onDispatchAttachedToWindow(new InputTransferToken(inputToken));
        } catch (RemoteException e) {
            Log.d(TAG,
                    "Failed to onDispatchAttachedToWindow to SCVH. Likely SCVH is already "
                            + "dead.");
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        setTag();
        if (mSurfacePackage != null) {
            dispatchScvhAttachedToHost();
        }
        getViewRootImpl().addSurfaceChangedCallback(this);
        mWindowStopped = false;
        mViewVisibility = getVisibility() == VISIBLE;
@@ -2220,7 +2189,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            applyTransactionOnVriDraw(transaction);
        }
        mSurfacePackage = p;
        dispatchScvhAttachedToHost();
        mSurfaceControlViewHostParent.attach(this);

        if (isFocused()) {
Loading