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
This commit is contained in:
Wale Ogunwale
2017-02-28 10:40:27 -08:00
parent 9ac082f8bb
commit 5aa8683bb7
3 changed files with 31 additions and 18 deletions

View File

@@ -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;
}
}

View File

@@ -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,17 +109,14 @@ class AlertWindowNotification {
.addAction(getTurnOffAction(context, mPackageName, mUid));
if (aInfo != null) {
final Bitmap bitmap = ((BitmapDrawable) pm.getApplicationIcon(aInfo)).getBitmap();
builder.setLargeIcon(bitmap);
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());
}
mNotificationManager.notify(mNotificationTag, NOTIFICATION_ID, builder.build());
}
private Notification.Action getTurnOffAction(Context context, String packageName, int uid) {

View File

@@ -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);