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

Commit b58847b3 authored by Marvin Ramin's avatar Marvin Ramin Committed by Android (Google) Code Review
Browse files

Merge "Add new AppOp for SYSTEM_APPLICATION_OVERLAY" into main

parents ddd1aae6 6af8a9d5
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -1715,9 +1715,13 @@ public class AppOpsManager {
    public static final int OP_SCENE_UNDERSTANDING_FINE =
            AppOpEnums.APP_OP_SCENE_UNDERSTANDING_FINE;

    /** @hide */
    public static final int OP_SYSTEM_APPLICATION_OVERLAY =
            AppOpEnums.APP_OP_SYSTEM_APPLICATION_OVERLAY;

    /** @hide */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static final int _NUM_OP = 164;
    public static final int _NUM_OP = 165;

    /**
     * All app ops represented as strings.
@@ -1884,7 +1888,8 @@ public class AppOpsManager {
            OPSTR_HEAD_TRACKING,
            OPSTR_SCENE_UNDERSTANDING_COARSE,
            OPSTR_SCENE_UNDERSTANDING_FINE,
            OPSTR_POST_PROMOTED_NOTIFICATIONS
            OPSTR_POST_PROMOTED_NOTIFICATIONS,
            OPSTR_SYSTEM_APPLICATION_OVERLAY
    })
    public @interface AppOpString {}

@@ -2691,6 +2696,10 @@ public class AppOpsManager {
    public static final String OPSTR_SCENE_UNDERSTANDING_FINE =
            "android:scene_understanding_fine";

    /** @hide Required to draw system application overlays. */
    public static final String OPSTR_SYSTEM_APPLICATION_OVERLAY =
            "android:system_application_overlay";

    /** {@link #sAppOpsToNote} not initialized yet for this op */
    private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
    /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2818,6 +2827,8 @@ public class AppOpsManager {
            OP_WRITE_SYSTEM_PREFERENCES,
            android.app.Flags.apiRichOngoingPermission()
                    ? OP_POST_PROMOTED_NOTIFICATIONS : OP_NONE,
            com.android.media.projection.flags.Flags.recordingOverlay()
                    ? OP_SYSTEM_APPLICATION_OVERLAY : OP_NONE,
    };

    @SuppressWarnings("FlaggedApi")
@@ -3354,6 +3365,11 @@ public class AppOpsManager {
                .setPermission(android.app.Flags.apiRichOngoingPermission()
                        ? Manifest.permission.POST_PROMOTED_NOTIFICATIONS : null)
                .build(),
        new AppOpInfo.Builder(OP_SYSTEM_APPLICATION_OVERLAY, OPSTR_SYSTEM_APPLICATION_OVERLAY,
                "SYSTEM_APPLICATION_OVERLAY")
                .setPermission(com.android.media.projection.flags.Flags.recordingOverlay()
                        ? Manifest.permission.SYSTEM_APPLICATION_OVERLAY : null)
                .build(),
    };

    // The number of longs needed to form a full bitmask of app ops
+47 −0
Original line number Diff line number Diff line
@@ -99,8 +99,10 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
@@ -149,6 +151,7 @@ import android.annotation.Size;
import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.ResourcesManager;
import android.app.UiModeManager;
import android.app.UiModeManager.ForceInvertStateChangeListener;
@@ -1594,6 +1597,14 @@ public final class ViewRootImpl implements ViewParent,
                    mWindowAttributes.privateFlags |= PRIVATE_FLAG_APP_PROGRESS_GENERATION_ALLOWED;
                }
                // TODO(b/395054309): Replace with calls to LayoutParams#setSystemApplicationOverlay
                //  in next API bump
                if (com.android.media.projection.flags.Flags.recordingOverlay()
                        && mWindowAttributes.type == TYPE_APPLICATION_OVERLAY
                        && hasSystemApplicationOverlayAppOp()) {
                    mWindowAttributes.privateFlags |= PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY;
                }
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
@@ -2143,6 +2154,13 @@ public final class ViewRootImpl implements ViewParent,
            // Calling this before copying prevents redundant LAYOUT_CHANGED.
            final int layoutInDisplayCutoutModeFromCaller = adjustLayoutInDisplayCutoutMode(attrs);
            // Keep PRIVATE_FLAG_SYSTEM_APPLICATION overlay if AppOp is granted
            // TODO(b/395054309): Replace with calls to LayoutParams#setSystemApplicationOverlay
            //  in next API bump
            if (shouldKeepSystemApplicationOverlay(mWindowAttributes, attrs)) {
                attrs.privateFlags |= PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY;
            }
            final int changes = mWindowAttributes.copyFrom(attrs);
            if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
                // Recompute system ui visibility.
@@ -2204,6 +2222,35 @@ public final class ViewRootImpl implements ViewParent,
        }
    }
    private boolean shouldKeepSystemApplicationOverlay(WindowManager.LayoutParams current,
            WindowManager.LayoutParams incoming) {
        if (!com.android.media.projection.flags.Flags.recordingOverlay()) {
            return false;
        }
        final boolean hasSystemApplicationOverlay =
                (current.privateFlags & PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY) != 0;
        if (!hasSystemApplicationOverlay) {
            return false;
        }
        if ((incoming.privateFlags & PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY) != 0) {
            return false;
        }
        if (!hasSystemApplicationOverlayAppOp()) {
            return false;
        }
        return true;
    }
    private boolean hasSystemApplicationOverlayAppOp() {
        return mContext.getSystemService(AppOpsManager.class).checkOpRawNoThrow(
                AppOpsManager.OPSTR_SYSTEM_APPLICATION_OVERLAY,
                mView.mContext.getAttributionSource().getUid(),
                mView.mContext.getPackageName(), null) == AppOpsManager.MODE_ALLOWED;
    }
    private int adjustLayoutInDisplayCutoutMode(WindowManager.LayoutParams attrs) {
        final int originalMode = attrs.layoutInDisplayCutoutMode;
        if ((attrs.privateFlags & (PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ android_app {
        "update_engine_aconfig_declarations",
        "appsearch_aconfig_flags",
        "aconfig_trade_in_mode_flags",
        "com.android.media.flags.projection-aconfig",
    ],
}

+16 −1
Original line number Diff line number Diff line
@@ -4480,7 +4480,22 @@

         <p>Not for use by third-party applications. -->
    <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"
                android:protectionLevel="signature|recents|role|installer"/>
        android:protectionLevel="signature|recents|role|installer|appop"
        android:featureFlag="com.android.media.projection.flags.recording_overlay" />

    <!-- @SystemApi @hide Allows an application to create windows using the type
         {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY},
         shown on top of all other apps.

         Allows an application to use
         {@link android.view.WindowManager.LayoutsParams#setSystemApplicationOverlay(boolean)}
         to create overlays that will stay visible, even if another window is requesting overlays to
         be hidden through {@link android.view.Window#setHideOverlayWindows(boolean)}.

         <p>Not for use by third-party applications. -->
    <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"
        android:protectionLevel="signature|recents|role|installer"
        android:featureFlag="!com.android.media.projection.flags.recording_overlay" />

    <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
         @hide
+32 −6
Original line number Diff line number Diff line
@@ -1090,6 +1090,7 @@ public final class MediaProjectionManagerService extends SystemService
        private IBinder mToken;
        private IBinder.DeathRecipient mDeathEater;
        private boolean mRestoreSystemAlertWindow;
        private boolean mRestoreSystemApplicationOverlay;
        private int mTaskId = -1;
        private LaunchCookie mLaunchCookie = null;
        private boolean mIsRecordingOverlay = false;
@@ -1230,8 +1231,20 @@ public final class MediaProjectionManagerService extends SystemService
                                mRestoreSystemAlertWindow = true;
                            }
                        }

                        // Recording overlays are only allowed for privileged, allowlisted callers.
                        // Those callers are allowed to hold APPLICATION_OVERLAY for the duration
                        // of the MediaProjection.
                        if (mIsRecordingOverlay) {
                            final int currentMode = mAppOps.unsafeCheckOpRawNoThrow(
                                    AppOpsManager.OP_SYSTEM_APPLICATION_OVERLAY, uid, packageName);
                            if (currentMode == AppOpsManager.MODE_DEFAULT) {
                                mAppOps.setUidMode(AppOpsManager.OP_SYSTEM_APPLICATION_OVERLAY, uid,
                                        AppOpsManager.MODE_ALLOWED);
                                mRestoreSystemApplicationOverlay = true;
                            }
                        }
                    } catch (PackageManager.NameNotFoundException e) {
                        Slog.w(TAG, "Package not found, aborting MediaProjection", e);
                        return;
                    } finally {
                        Binder.restoreCallingIdentity(token);
@@ -1257,9 +1270,10 @@ public final class MediaProjectionManagerService extends SystemService
                            + "pid=" + Binder.getCallingPid() + ")");
                    return;
                }
                if (mRestoreSystemAlertWindow) {

                final long token = Binder.clearCallingIdentity();
                try {
                    if (mRestoreSystemAlertWindow) {
                        // Put the appop back how it was, unless it has been changed from what
                        // we set it to.
                        // Note that WindowManager takes care of removing any existing overlay
@@ -1271,10 +1285,22 @@ public final class MediaProjectionManagerService extends SystemService
                                    AppOpsManager.MODE_DEFAULT);
                        }
                        mRestoreSystemAlertWindow = false;

                    }
                    if (mRestoreSystemApplicationOverlay) {
                        final int appOverlayMode = mAppOps.unsafeCheckOpRawNoThrow(
                                AppOpsManager.OP_SYSTEM_APPLICATION_OVERLAY, uid, packageName);
                        if (appOverlayMode == AppOpsManager.MODE_ALLOWED) {
                            mAppOps.setUidMode(AppOpsManager.OP_SYSTEM_APPLICATION_OVERLAY, uid,
                                    AppOpsManager.MODE_DEFAULT);
                        }
                        mRestoreSystemApplicationOverlay = false;
                    }

                } finally {

                    Binder.restoreCallingIdentity(token);
                }
                }
                Slog.d(TAG, "Content Recording: handling stopping this projection token"
                        + " createTime= " + mCreateTimeMillis
                        + " countStarts= " + mCountStarts);
Loading