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

Commit 9b05c61a authored by Scott Greenwald's avatar Scott Greenwald
Browse files

move scoring, sound, vibration, and lights into a handler

As a prelude to introducing fancier scoring functions, this CL
moves scoring and everything that depends on it into a handler.
This allows the NotificationManagerService to report back to the
calling process right away about whether or not the notification
is valid; not blocking while score is computed, and non-statusbar
notification modalities are activated.

Change-Id: Iaf77bc89544bb7bcb7adeda60885d74c3170541c
parent 10113a44
Loading
Loading
Loading
Loading
+235 −210
Original line number Diff line number Diff line
@@ -1601,8 +1601,10 @@ public class NotificationManagerService extends INotificationManager.Stub

    // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
    // uid/pid of another application)
    public void enqueueNotificationInternal(String pkg, String basePkg, int callingUid,
            int callingPid, String tag, int id, Notification notification, int[] idOut, int userId)

    public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
            final int callingPid, final String tag, final int id, final Notification notification,
            int[] idOut, int incomingUserId)
    {
        if (DBG) {
            Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification);
@@ -1610,8 +1612,8 @@ public class NotificationManagerService extends INotificationManager.Stub
        checkCallerIsSystemOrSameApp(pkg);
        final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg));

        userId = ActivityManager.handleIncomingUser(callingPid,
                callingUid, userId, true, false, "enqueueNotification", pkg);
        final int userId = ActivityManager.handleIncomingUser(callingPid,
                callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
        final UserHandle user = new UserHandle(userId);

        // Limit the number of notifications that any given package except the android
@@ -1653,15 +1655,25 @@ public class NotificationManagerService extends INotificationManager.Stub
            }
        }

        mHandler.post(new Runnable() {
            @Override
            public void run() {

                // === Scoring ===

                // 0. Sanitize inputs
        notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX);
                notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
                        Notification.PRIORITY_MAX);
                // Migrate notification flags to scores
                if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) {
            if (notification.priority < Notification.PRIORITY_MAX) notification.priority = Notification.PRIORITY_MAX;
        } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {
            if (notification.priority < Notification.PRIORITY_HIGH) notification.priority = Notification.PRIORITY_HIGH;
                    if (notification.priority < Notification.PRIORITY_MAX) {
                        notification.priority = Notification.PRIORITY_MAX;
                    }
                } else if (SCORE_ONGOING_HIGHER &&
                        0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {
                    if (notification.priority < Notification.PRIORITY_HIGH) {
                        notification.priority = Notification.PRIORITY_HIGH;
                    }
                }

                // 1. initial score: buckets of 10, around the app
@@ -1675,7 +1687,8 @@ public class NotificationManagerService extends INotificationManager.Stub
                if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) {
                    if (!isSystemNotification) {
                        score = JUNK_SCORE;
                Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request.");
                        Slog.e(TAG, "Suppressing notification from package " + pkg
                                + " by user request.");
                    }
                }

@@ -1769,7 +1782,8 @@ public class NotificationManagerService extends INotificationManager.Stub
                        }
                        // ATTENTION: in a future release we will bail out here
                        // so that we do not play sounds, show lights, etc. for invalid notifications
                Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName());
                        Slog.e(TAG, "WARNING: In a future release this will crash the app: "
                                + n.getPackageName());
                    }

                    // If we're not supposed to beep, vibrate, etc. then don't.
@@ -1786,11 +1800,13 @@ public class NotificationManagerService extends INotificationManager.Stub

                        // sound

                // should we use the default notification sound? (indicated either by DEFAULT_SOUND
                // or because notification.sound is pointing at Settings.System.NOTIFICATION_SOUND)
                        // should we use the default notification sound? (indicated either by
                        // DEFAULT_SOUND or because notification.sound is pointing at
                        // Settings.System.NOTIFICATION_SOUND)
                        final boolean useDefaultSound =
                       (notification.defaults & Notification.DEFAULT_SOUND) != 0
                    || Settings.System.DEFAULT_NOTIFICATION_URI.equals(notification.sound);
                               (notification.defaults & Notification.DEFAULT_SOUND) != 0 ||
                                       Settings.System.DEFAULT_NOTIFICATION_URI
                                               .equals(notification.sound);

                        Uri soundUri = null;
                        boolean hasValidSound = false;
@@ -1816,8 +1832,8 @@ public class NotificationManagerService extends INotificationManager.Stub
                                audioStreamType = DEFAULT_STREAM_TYPE;
                            }
                            mSoundNotification = r;
                    // do not play notifications if stream volume is 0
                    // (typically because ringer mode is silent) or if speech recognition is active.
                            // do not play notifications if stream volume is 0 (typically because
                            // ringer mode is silent) or if speech recognition is active.
                            if ((audioManager.getStreamVolume(audioStreamType) != 0)
                                    && !audioManager.isSpeechRecognitionActive()) {
                                final long identity = Binder.clearCallingIdentity();
@@ -1837,37 +1853,43 @@ public class NotificationManagerService extends INotificationManager.Stub
                        // Does the notification want to specify its own vibration?
                        final boolean hasCustomVibrate = notification.vibrate != null;

                // new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
                // and no other vibration is specified, we fall back to vibration
                        // new in 4.2: if there was supposed to be a sound and we're in vibrate
                        // mode, and no other vibration is specified, we fall back to vibration
                        final boolean convertSoundToVibration =
                                   !hasCustomVibrate
                                && hasValidSound
                        && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
                                && (audioManager.getRingerMode()
                                           == AudioManager.RINGER_MODE_VIBRATE);

                        // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
                        final boolean useDefaultVibrate =
                                (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;

                        if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate)
                        && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) {
                                && !(audioManager.getRingerMode()
                                        == AudioManager.RINGER_MODE_SILENT)) {
                            mVibrateNotification = r;

                            if (useDefaultVibrate || convertSoundToVibration) {
                        // Escalate privileges so we can use the vibrator even if the notifying app
                        // does not have the VIBRATE permission.
                                // Escalate privileges so we can use the vibrator even if the
                                // notifying app does not have the VIBRATE permission.
                                long identity = Binder.clearCallingIdentity();
                                try {
                                    mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
                                        useDefaultVibrate ? mDefaultVibrationPattern
                                            : mFallbackVibrationPattern,
                                ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
                                        ((notification.flags & Notification.FLAG_INSISTENT) != 0)
                                                ? 0: -1);
                                } finally {
                                    Binder.restoreCallingIdentity(identity);
                                }
                            } else if (notification.vibrate.length > 1) {
                        // If you want your own vibration pattern, you need the VIBRATE permission
                        mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate,
                            ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
                                // If you want your own vibration pattern, you need the VIBRATE
                                // permission
                                mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
                                        notification.vibrate,
                                    ((notification.flags & Notification.FLAG_INSISTENT) != 0)
                                            ? 0: -1);
                            }
                        }
                    }
@@ -1879,7 +1901,8 @@ public class NotificationManagerService extends INotificationManager.Stub
                        mLedNotification = null;
                    }
                    //Slog.i(TAG, "notification.lights="
            //        + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) != 0));
                    //        + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS)
                    //                  != 0));
                    if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0
                            && canInterrupt) {
                        mLights.add(r);
@@ -1891,6 +1914,8 @@ public class NotificationManagerService extends INotificationManager.Stub
                        }
                    }
                }
            }
        });

        idOut[0] = id;
    }