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

Commit 7f6c231a authored by Jeff Brown's avatar Jeff Brown
Browse files

Add setting to redirect vibrator to game controller.

Bug: 6334179
Change-Id: I70093e38824ea3e5cf9cf242d1d7b6d26115ed80
parent 90aba7ca
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1463,6 +1463,20 @@ public final class Settings {
         */
        public static final String VIBRATE_ON = "vibrate_on";

        /**
         * If 1, redirects the system vibrator to all currently attached input devices
         * that support vibration.  If there are no such input devices, then the system
         * vibrator is used instead.
         * If 0, does not register the system vibrator.
         *
         * This setting is mainly intended to provide a compatibility mechanism for
         * applications that only know about the system vibrator and do not use the
         * input device vibrator API.
         *
         * @hide
         */
        public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices";

        /**
         * Ringer volume. This is used internally, changing this value will not
         * change the volume. See AudioManager.
@@ -1970,6 +1984,7 @@ public final class Settings {
            SCREEN_BRIGHTNESS_MODE,
            SCREEN_AUTO_BRIGHTNESS_ADJ,
            VIBRATE_ON,
            VIBRATE_INPUT_DEVICES,
            MODE_RINGER,
            MODE_RINGER_STREAMS_AFFECTED,
            MUTE_STREAMS_AFFECTED,
+9 −1
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ class ServerThread extends Thread {
        LightsService lights = null;
        PowerManagerService power = null;
        BatteryService battery = null;
        VibratorService vibrator = null;
        AlarmManagerService alarm = null;
        NetworkManagementService networkManagement = null;
        NetworkStatsService networkStats = null;
@@ -203,7 +204,8 @@ class ServerThread extends Thread {
            ServiceManager.addService("battery", battery);

            Slog.i(TAG, "Vibrator Service");
            ServiceManager.addService("vibrator", new VibratorService(context));
            vibrator = new VibratorService(context);
            ServiceManager.addService("vibrator", vibrator);

            // only initialize the power service after we have started the
            // lights service, content providers and the battery service.
@@ -645,6 +647,12 @@ class ServerThread extends Thread {

        // It is now time to start up the app processes...

        try {
            vibrator.systemReady();
        } catch (Throwable e) {
            reportWtf("making Vibrator Service ready", e);
        }

        if (devicePolicy != null) {
            try {
                devicePolicy.systemReady();
+139 −17
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.IVibratorService;
import android.os.PowerManager;
@@ -29,18 +31,41 @@ import android.os.RemoteException;
import android.os.IBinder;
import android.os.Binder;
import android.os.SystemClock;
import android.os.Vibrator;
import android.os.WorkSource;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.view.InputDevice;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;

public class VibratorService extends IVibratorService.Stub {
public class VibratorService extends IVibratorService.Stub
        implements InputManager.InputDeviceListener {
    private static final String TAG = "VibratorService";

    private final LinkedList<Vibration> mVibrations;
    private Vibration mCurrentVibration;
    private final WorkSource mTmpWorkSource = new WorkSource();
    private final Handler mH = new Handler();

    private final Context mContext;
    private final PowerManager.WakeLock mWakeLock;
    private InputManager mIm;

    volatile VibrateThread mThread;

    // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are
    // to be acquired
    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
    private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
    private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators

    native static boolean vibratorExists();
    native static void vibratorOn(long milliseconds);
    native static void vibratorOff();

    private class Vibration implements IBinder.DeathRecipient {
        private final IBinder mToken;
@@ -112,8 +137,21 @@ public class VibratorService extends IVibratorService.Stub {
        context.registerReceiver(mIntentReceiver, filter);
    }

    public void systemReady() {
        mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
        mContext.getContentResolver().registerContentObserver(
                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true,
                new ContentObserver(mH) {
                    @Override
                    public void onChange(boolean selfChange) {
                        updateVibrateInputDevicesSetting();
                    }
                });
        updateVibrateInputDevicesSetting();
    }

    public boolean hasVibrator() {
        return vibratorExists();
        return doVibratorExists();
    }

    public void vibrate(long milliseconds, IBinder token) {
@@ -131,6 +169,7 @@ public class VibratorService extends IVibratorService.Stub {
            // longer than milliseconds.
            return;
        }

        Vibration vib = new Vibration(token, milliseconds, uid);
        synchronized (mVibrations) {
            removeVibrationLocked(token);
@@ -240,7 +279,7 @@ public class VibratorService extends IVibratorService.Stub {
            }
            mThread = null;
        }
        vibratorOff();
        doVibratorOff();
        mH.removeCallbacks(mVibrationRunnable);
    }

@@ -257,7 +296,7 @@ public class VibratorService extends IVibratorService.Stub {
    // Lock held on mVibrations
    private void startVibrationLocked(final Vibration vib) {
        if (vib.mTimeout != 0) {
            vibratorOn(vib.mTimeout);
            doVibratorOn(vib.mTimeout);
            mH.postDelayed(mVibrationRunnable, vib.mTimeout);
        } else {
            // mThread better be null here. doCancelVibrate should always be
@@ -295,6 +334,100 @@ public class VibratorService extends IVibratorService.Stub {
        }
    }

    private void updateVibrateInputDevicesSetting() {
        synchronized (mInputDeviceVibrators) {
            mVibrateInputDevicesSetting = false;
            try {
                mVibrateInputDevicesSetting = Settings.System.getInt(mContext.getContentResolver(),
                        Settings.System.VIBRATE_INPUT_DEVICES) > 0;
            } catch (SettingNotFoundException snfe) {
            }

            if (mVibrateInputDevicesSetting) {
                if (!mInputDeviceListenerRegistered) {
                    mInputDeviceListenerRegistered = true;
                    mIm.registerInputDeviceListener(this, mH);
                }
            } else {
                if (mInputDeviceListenerRegistered) {
                    mInputDeviceListenerRegistered = false;
                    mIm.unregisterInputDeviceListener(this);
                }
            }

            updateInputDeviceVibrators();
        }
    }

    private void updateInputDeviceVibrators() {
        synchronized (mVibrations) {
            doCancelVibrateLocked();

            synchronized (mInputDeviceVibrators) {
                mInputDeviceVibrators.clear();
                if (mVibrateInputDevicesSetting) {
                    int[] ids = mIm.getInputDeviceIds();
                    for (int i = 0; i < ids.length; i++) {
                        InputDevice device = mIm.getInputDevice(ids[i]);
                        Vibrator vibrator = device.getVibrator();
                        if (vibrator.hasVibrator()) {
                            mInputDeviceVibrators.add(vibrator);
                        }
                    }
                }
            }

            startNextVibrationLocked();
        }
    }

    @Override
    public void onInputDeviceAdded(int deviceId) {
        updateInputDeviceVibrators();
    }

    @Override
    public void onInputDeviceChanged(int deviceId) {
        updateInputDeviceVibrators();
    }

    @Override
    public void onInputDeviceRemoved(int deviceId) {
        updateInputDeviceVibrators();
    }

    private boolean doVibratorExists() {
        synchronized (mInputDeviceVibrators) {
            return !mInputDeviceVibrators.isEmpty() || vibratorExists();
        }
    }

    private void doVibratorOn(long millis) {
        synchronized (mInputDeviceVibrators) {
            final int vibratorCount = mInputDeviceVibrators.size();
            if (vibratorCount != 0) {
                for (int i = 0; i < vibratorCount; i++) {
                    mInputDeviceVibrators.get(i).vibrate(millis);
                }
            } else {
                vibratorOn(millis);
            }
        }
    }

    private void doVibratorOff() {
        synchronized (mInputDeviceVibrators) {
            final int vibratorCount = mInputDeviceVibrators.size();
            if (vibratorCount != 0) {
                for (int i = 0; i < vibratorCount; i++) {
                    mInputDeviceVibrators.get(i).cancel();
                }
            } else {
                vibratorOff();
            }
        }
    }

    private class VibrateThread extends Thread {
        final Vibration mVibration;
        boolean mDone;
@@ -350,7 +483,7 @@ public class VibratorService extends IVibratorService.Stub {
                        // duration is saved for delay() at top of loop
                        duration = pattern[index++];
                        if (duration > 0) {
                            VibratorService.this.vibratorOn(duration);
                            VibratorService.this.doVibratorOn(duration);
                        }
                    } else {
                        if (repeat < 0) {
@@ -394,15 +527,4 @@ public class VibratorService extends IVibratorService.Stub {
            }
        }
    };

    private Handler mH = new Handler();

    private final Context mContext;
    private final PowerManager.WakeLock mWakeLock;

    volatile VibrateThread mThread;

    native static boolean vibratorExists();
    native static void vibratorOn(long milliseconds);
    native static void vibratorOff();
}