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

Commit 9688fea7 authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Add setting to redirect vibrator to game controller."

parents 75bf7446 7f6c231a
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();
}