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

Commit 5aa8683b authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed some issues with alert window notifications

- Don't hold window manager lock while calling into notification
manager since it can end up calling into activity manager.
- Fixed issue with using checkCallingPermission() to check if the
system has the internal system window permission. This call fails
if it isn't a binder call. Change to use checkCallingorSelfPermission()
instead.
- Fixed class cast exception while getting app icon by using
IconUtilities class to the the drawable to bitmap convertion.

Change-Id: I4ef380618f558a8aac5b152d97536a614040397f
Fixes: 35780846
Fixes: 35846667
Fixes: 35854470
Bug: 35657567
Test: cts/hostsidetests/.../run-test CtsWindowManagerHostTestCases android.server.cts.AlertWindowsTests
parent 9ac082f8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -2398,8 +2398,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
             * permission to add alert windows that aren't
             * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
             */
            return (mContext.checkCallingPermission(INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED)
                    ? ADD_OKAY : ADD_PERMISSION_DENIED;
            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
        }

        // check if user has enabled this operation. SecurityException will be thrown if this app
@@ -2420,8 +2420,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            default:
                // in the default mode, we will make a decision here based on
                // checkCallingPermission()
                return (mContext.checkCallingPermission(SYSTEM_ALERT_WINDOW) == PERMISSION_GRANTED)
                        ? ADD_OKAY : ADD_PERMISSION_DENIED;
                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
        }
    }

+25 −13
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.wm;

import static android.app.Notification.VISIBILITY_PRIVATE;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.content.Context.NOTIFICATION_SERVICE;
@@ -34,8 +33,10 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

import com.android.internal.R;
import com.android.server.policy.IconUtilities;

/** Displays an ongoing notification for a process displaying an alert window */
class AlertWindowNotification {
@@ -50,6 +51,7 @@ class AlertWindowNotification {
    private final String mPackageName;
    private final int mUid;
    private boolean mCancelled;
    private IconUtilities mIconUtilities;

    AlertWindowNotification(WindowManagerService service, String packageName, int uid) {
        mService = service;
@@ -59,20 +61,33 @@ class AlertWindowNotification {
                (NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
        mNotificationTag = CHANNEL_PREFIX + mPackageName;
        mRequestCode = sNextRequestCode++;
        mIconUtilities = new IconUtilities(mService.mContext);

        // We can't create/post the notification while the window manager lock is held since it will
        // end up calling into activity manager. So, we post a message to do it later.
        mService.mH.post(this::postNotification);
        mService.mH.post(this::onPostNotification);
    }

    /** Cancels the notification */
    void cancel() {
        // We can't call into NotificationManager with WM lock held since it might call into AM.
        // So, we post a message to do it later.
        mService.mH.post(this::onCancelNotification);
    }

    /** Don't call with the window manager lock held! */
    private void onCancelNotification() {
        mNotificationManager.cancel(mNotificationTag, NOTIFICATION_ID);
        mCancelled = true;
    }

    /** Don't call with the window manager lock held! */
    private void postNotification() {
    private void onPostNotification() {
        if (mCancelled) {
            // Notification was cancelled, so nothing more to do...
            return;
        }

        final Context context = mService.mContext;
        final PackageManager pm = context.getPackageManager();
        final ApplicationInfo aInfo = getApplicationInfo(pm, mPackageName);
@@ -94,18 +109,15 @@ class AlertWindowNotification {
                .addAction(getTurnOffAction(context, mPackageName, mUid));

        if (aInfo != null) {
            final Bitmap bitmap = ((BitmapDrawable) pm.getApplicationIcon(aInfo)).getBitmap();
            final Drawable drawable = pm.getApplicationIcon(aInfo);
            if (drawable != null) {
                final Bitmap bitmap = mIconUtilities.createIconBitmap(drawable);
                builder.setLargeIcon(bitmap);
            }

        synchronized (mService.mWindowMap) {
            if (mCancelled) {
                // Notification was cancelled, so nothing more to do...
                return;
        }

        mNotificationManager.notify(mNotificationTag, NOTIFICATION_ID, builder.build());
    }
    }

    private Notification.Action getTurnOffAction(Context context, String packageName, int uid) {
        final Intent intent = new Intent(ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION);
+2 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ public class Session extends IWindowSession.Stub
        mUid = Binder.getCallingUid();
        mPid = Binder.getCallingPid();
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
        mCanAddInternalSystemWindow = service.mContext.checkCallingPermission(
        mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
                INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
        StringBuilder sb = new StringBuilder();
        sb.append("Session{");
@@ -664,6 +664,7 @@ public class Session extends IWindowSession.Stub

    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
                pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
                pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
                pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
                pw.print(" mClientDead="); pw.print(mClientDead);