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

Commit ceb4813e authored by Lais Andrade's avatar Lais Andrade
Browse files

Log ignored external vibrations in dumpsys

Add log entries for ignored external vibration when the device doesn't
have external control capability or when the requesting app doesn't have
the required VIBRATE permission.

This will help debugging cases where vibration might not be felt by the
user but will not log error if triggered from the audio-coupled path.

Also improve logs from vibrations created by performHapticFeedback to
log the original feedback constant id requested, to help identifying the
source of the vibrations in scenarios when the original app is system or
SysUI.

Fix: 304481005
Test: atest VibratorManagerServiceTest
Change-Id: Ie393e8f33663f818b40fe9a49606e983ad2c53bf
parent 4e21ef74
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ message VibrationProto {
    reserved 6; // prev int32 status

    // Also used by VibrationReported from frameworks/proto_logging/stats/atoms.proto.
    // Next Tag: 26
    // Next Tag: 29
    enum Status {
        UNKNOWN = 0;
        RUNNING = 1;
@@ -135,7 +135,6 @@ message VibrationProto {
        IGNORED_ERROR_TOKEN= 14;
        IGNORED_APP_OPS = 15;
        IGNORED_BACKGROUND = 16;
        IGNORED_UNKNOWN_VIBRATION = 17;
        IGNORED_UNSUPPORTED = 18;
        IGNORED_FOR_EXTERNAL = 19;
        IGNORED_FOR_HIGHER_IMPORTANCE = 20;
@@ -146,6 +145,8 @@ message VibrationProto {
        IGNORED_SUPERSEDED = 25;
        IGNORED_FROM_VIRTUAL_DEVICE = 26;
        IGNORED_ON_WIRELESS_CHARGER = 27;
        IGNORED_MISSING_PERMISSION = 28;
        reserved 17; // prev IGNORED_UNKNOWN_VIBRATION
    }
}

+1 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ abstract class Vibration {
        IGNORED_ERROR_TOKEN(VibrationProto.IGNORED_ERROR_TOKEN),
        IGNORED_APP_OPS(VibrationProto.IGNORED_APP_OPS),
        IGNORED_BACKGROUND(VibrationProto.IGNORED_BACKGROUND),
        IGNORED_UNKNOWN_VIBRATION(VibrationProto.IGNORED_UNKNOWN_VIBRATION),
        IGNORED_MISSING_PERMISSION(VibrationProto.IGNORED_MISSING_PERMISSION),
        IGNORED_UNSUPPORTED(VibrationProto.IGNORED_UNSUPPORTED),
        IGNORED_FOR_EXTERNAL(VibrationProto.IGNORED_FOR_EXTERNAL),
        IGNORED_FOR_HIGHER_IMPORTANCE(VibrationProto.IGNORED_FOR_HIGHER_IMPORTANCE),
+38 −34
Original line number Diff line number Diff line
@@ -436,26 +436,26 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
            IBinder token, boolean fromIme) {
        HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
        if (hapticVibrationProvider == null) {
            Slog.w(TAG, "performHapticFeedback; haptic vibration provider not ready.");
            Slog.e(TAG, "performHapticFeedback; haptic vibration provider not ready.");
            return null;
        }
        if (hapticVibrationProvider.isRestrictedHapticFeedback(constant)
                && !hasPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS)) {
            Slog.w(TAG, "performHapticFeedback; no permission for effect " + constant);
            Slog.w(TAG, "performHapticFeedback; no permission for system constant " + constant);
            return null;
        }
        VibrationEffect effect = hapticVibrationProvider.getVibrationForHapticFeedback(constant);
        if (effect == null) {
            Slog.w(TAG, "performHapticFeedback; vibration absent for effect " + constant);
            Slog.w(TAG, "performHapticFeedback; vibration absent for constant " + constant);
            return null;
        }
        CombinedVibration combinedVibration = CombinedVibration.createParallel(effect);
        CombinedVibration vib = CombinedVibration.createParallel(effect);
        VibrationAttributes attrs =
                hapticVibrationProvider.getVibrationAttributesForHapticFeedback(
                        constant, /* bypassVibrationIntensitySetting= */ always, fromIme);
        reason = "performHapticFeedback(constant=" + constant + "): " + reason;
        VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, constant);
        return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, combinedVibration, attrs,
                "performHapticFeedback: " + reason, token);
        return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, vib, attrs, reason, token);
    }

    /**
@@ -1951,39 +1951,34 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
    /** Implementation of {@link IExternalVibratorService} to be triggered on external control. */
    @VisibleForTesting
    final class ExternalVibratorService extends IExternalVibratorService.Stub {
        private static final ExternalVibrationScale SCALE_MUTE = new ExternalVibrationScale();

        static {
            SCALE_MUTE.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
        }

        @Override
        public ExternalVibrationScale onExternalVibrationStart(ExternalVibration vib) {
            // Create Vibration.Stats as close to the received request as possible, for tracking.
            ExternalVibrationHolder vibHolder = new ExternalVibrationHolder(vib);
            // Mute the request until we run all the checks and accept the vibration.
            vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
            boolean alreadyUnderExternalControl = false;
            boolean waitForCompletion = false;

            synchronized (mLock) {
                if (!hasExternalControlCapability()) {
                return SCALE_MUTE;
                    endVibrationAndWriteStatsLocked(vibHolder,
                            new Vibration.EndInfo(Vibration.Status.IGNORED_UNSUPPORTED));
                    return vibHolder.scale;
                }

                if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
                        vib.getUid(), -1 /*owningUid*/, true /*exported*/)
                        != PackageManager.PERMISSION_GRANTED) {
                    Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
                            + " tried to play externally controlled vibration"
                            + " without VIBRATE permission, ignoring.");
                return SCALE_MUTE;
            }

            // Create Vibration.Stats as close to the received request as possible, for tracking.
            ExternalVibrationHolder vibHolder = new ExternalVibrationHolder(vib);
            VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
                    /* effect= */ null);
            if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
                // Force update of user settings before checking if this vibration effect should
                // be ignored or scaled.
                mVibrationSettings.update();
                    endVibrationAndWriteStatsLocked(vibHolder,
                            new Vibration.EndInfo(Vibration.Status.IGNORED_MISSING_PERMISSION));
                    return vibHolder.scale;
                }

            boolean alreadyUnderExternalControl = false;
            boolean waitForCompletion = false;
            synchronized (mLock) {
                Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
                        vibHolder.callerInfo);

@@ -2001,8 +1996,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                }

                if (vibrationEndInfo != null) {
                    vibHolder.scale = SCALE_MUTE;
                    // Failed to start the vibration, end it and report metrics right away.
                    endVibrationAndWriteStatsLocked(vibHolder, vibrationEndInfo);
                    return vibHolder.scale;
                }
@@ -2040,6 +2033,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                                    vibHolder.callerInfo),
                            /* continueExternalControl= */ true);
                }

                VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
                        /* effect= */ null);
                if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
                    // Force update of user settings before checking if this vibration effect should
                    // be ignored or scaled.
                    mVibrationSettings.update();
                }

                mCurrentExternalVibration = vibHolder;
                vibHolder.linkToDeath();
                vibHolder.scale.scaleLevel = mVibrationScaler.getScaleLevel(attrs.getUsage());
@@ -2055,8 +2057,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                        endExternalVibrateLocked(
                                new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_CANCELLING),
                                /* continueExternalControl= */ false);
                        // Mute the request, vibration will be ignored.
                        vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
                    }
                    return SCALE_MUTE;
                    return vibHolder.scale;
                }
            }
            if (!alreadyUnderExternalControl) {