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

Commit 69721d64 authored by Beverly's avatar Beverly Committed by Beverly Tai
Browse files

(Behind flag) Wireless charging vibration feedback

- to turn vibration feedback on wireless charging:
    adb shell settings put global charging_vibration_enabled 1

Test: manual
Bug: 74505795
Change-Id: I177bc05e75bb9e66a88b45432eee778ab619e28f
parent cd7f9963
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -8614,6 +8614,14 @@ public final class Settings {
        private static final Validator CHARGING_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
        private static final Validator CHARGING_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
        /**
         * Whether to vibrate for wireless charging events.
         * @hide
         */
        public static final String CHARGING_VIBRATION_ENABLED = "charging_vibration_enabled";
        private static final Validator CHARGING_VIBRATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
        /**
        /**
         * Whether we keep the device on while the device is plugged in.
         * Whether we keep the device on while the device is plugged in.
         * Supported values are:
         * Supported values are:
@@ -12023,6 +12031,7 @@ public final class Settings {
            PRIVATE_DNS_SPECIFIER,
            PRIVATE_DNS_SPECIFIER,
            SOFT_AP_TIMEOUT_ENABLED,
            SOFT_AP_TIMEOUT_ENABLED,
            ZEN_DURATION,
            ZEN_DURATION,
            CHARGING_VIBRATION_ENABLED,
        };
        };
        /**
        /**
@@ -12066,6 +12075,7 @@ public final class Settings {
                    WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
                    WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
            VALIDATORS.put(APP_AUTO_RESTRICTION_ENABLED, APP_AUTO_RESTRICTION_ENABLED_VALIDATOR);
            VALIDATORS.put(APP_AUTO_RESTRICTION_ENABLED, APP_AUTO_RESTRICTION_ENABLED_VALIDATOR);
            VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
            VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
            VALIDATORS.put(CHARGING_VIBRATION_ENABLED, CHARGING_VIBRATION_ENABLED_VALIDATOR);
        }
        }
        /**
        /**
+41 −8
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.hardware.input.InputManagerInternal;
import android.hardware.input.InputManagerInternal;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.RingtoneManager;
@@ -40,20 +41,21 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.WorkSource;
import android.os.WorkSource;
import android.provider.Settings;
import android.provider.Settings;
import android.util.EventLog;
import android.util.EventLog;
import android.util.Slog;
import android.util.Slog;
import android.view.inputmethod.InputMethodManagerInternal;
import android.view.inputmethod.InputMethodManagerInternal;


import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.IBatteryStats;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.EventLogTags;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.statusbar.StatusBarManagerInternal;


/**
/**
 * Sends broadcasts about important power state changes.
 * Sends broadcasts about important power state changes.
@@ -88,6 +90,21 @@ final class Notifier {
    private static final int MSG_PROFILE_TIMED_OUT = 5;
    private static final int MSG_PROFILE_TIMED_OUT = 5;
    private static final int MSG_WIRED_CHARGING_STARTED = 6;
    private static final int MSG_WIRED_CHARGING_STARTED = 6;


    private static final long[] WIRELESS_VIBRATION_TIME = {
            40, 40, 40, 40, 40, 40, 40, 40, 40, // ramp-up sampling rate = 40ms
            40, 40, 40, 40, 40, 40, 40 // ramp-down sampling rate = 40ms
    };
    private static final int[] WIRELESS_VIBRATION_AMPLITUDE = {
            1, 4, 11, 25, 44, 67, 91, 114, 123, // ramp-up amplitude (from 0 to 50%)
            103, 79, 55, 34, 17, 7, 2 // ramp-up amplitude
    };
    private static final VibrationEffect WIRELESS_CHARGING_VIBRATION_EFFECT =
            VibrationEffect.createWaveform(WIRELESS_VIBRATION_TIME, WIRELESS_VIBRATION_AMPLITUDE,
                    -1);
    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .build();

    private final Object mLock = new Object();
    private final Object mLock = new Object();


    private final Context mContext;
    private final Context mContext;
@@ -100,6 +117,7 @@ final class Notifier {
    private final InputMethodManagerInternal mInputMethodManagerInternal;
    private final InputMethodManagerInternal mInputMethodManagerInternal;
    @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
    @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
    private final TrustManager mTrustManager;
    private final TrustManager mTrustManager;
    private final Vibrator mVibrator;


    private final NotifierHandler mHandler;
    private final NotifierHandler mHandler;
    private final Intent mScreenOnIntent;
    private final Intent mScreenOnIntent;
@@ -146,6 +164,7 @@ final class Notifier {
        mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
        mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
        mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
        mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
        mTrustManager = mContext.getSystemService(TrustManager.class);
        mTrustManager = mContext.getSystemService(TrustManager.class);
        mVibrator = mContext.getSystemService(Vibrator.class);


        mHandler = new NotifierHandler(looper);
        mHandler = new NotifierHandler(looper);
        mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
        mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
@@ -719,14 +738,9 @@ final class Notifier {
     * Plays the wireless charging sound for both wireless and non-wireless charging
     * Plays the wireless charging sound for both wireless and non-wireless charging
     */
     */
    private void playChargingStartedSound() {
    private void playChargingStartedSound() {
        final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
        final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
                == Settings.Global.ZEN_MODE_OFF;
        final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
        final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
                Settings.Global.CHARGING_STARTED_SOUND);
                Settings.Global.CHARGING_STARTED_SOUND);
        if (enabled && dndOff && soundPath != null) {
        if (isChargingFeedbackEnabled() && soundPath != null) {
            final Uri soundUri = Uri.parse("file://" + soundPath);
            final Uri soundUri = Uri.parse("file://" + soundPath);
            if (soundUri != null) {
            if (soundUri != null) {
                final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
                final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
@@ -739,6 +753,7 @@ final class Notifier {
    }
    }


    private void showWirelessChargingStarted(int batteryLevel) {
    private void showWirelessChargingStarted(int batteryLevel) {
        playWirelessChargingVibration();
        playChargingStartedSound();
        playChargingStartedSound();
        if (mStatusBarManagerInternal != null) {
        if (mStatusBarManagerInternal != null) {
            mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
            mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
@@ -755,6 +770,23 @@ final class Notifier {
        mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
        mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
    }
    }


    private void playWirelessChargingVibration() {
        final boolean vibrateEnabled = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.CHARGING_VIBRATION_ENABLED, 0) != 0;
        if (vibrateEnabled && isChargingFeedbackEnabled()) {
            mVibrator.vibrate(WIRELESS_CHARGING_VIBRATION_EFFECT, VIBRATION_ATTRIBUTES);
        }
    }

    private boolean isChargingFeedbackEnabled() {
        final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
        final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
                == Settings.Global.ZEN_MODE_OFF;
        return enabled && dndOff;
    }

    private final class NotifierHandler extends Handler {
    private final class NotifierHandler extends Handler {


        public NotifierHandler(Looper looper) {
        public NotifierHandler(Looper looper) {
@@ -780,6 +812,7 @@ final class Notifier {
                    break;
                    break;
                case MSG_WIRED_CHARGING_STARTED:
                case MSG_WIRED_CHARGING_STARTED:
                    showWiredChargingStarted();
                    showWiredChargingStarted();
                    break;
            }
            }
        }
        }
    }
    }