diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-04-13 20:38:38 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-04-13 20:38:38 -0700 |
commit | 7f6c231a76f0bedaf9655a24707737d343244312 (patch) | |
tree | 63eaaa6255f04d34dd125da1459d2b2e70753002 | |
parent | 90aba7caac78b407347b930cfb6ff7d6658ac90a (diff) | |
download | frameworks_base-7f6c231a76f0bedaf9655a24707737d343244312.zip frameworks_base-7f6c231a76f0bedaf9655a24707737d343244312.tar.gz frameworks_base-7f6c231a76f0bedaf9655a24707737d343244312.tar.bz2 |
Add setting to redirect vibrator to game controller.
Bug: 6334179
Change-Id: I70093e38824ea3e5cf9cf242d1d7b6d26115ed80
-rw-r--r-- | core/java/android/provider/Settings.java | 15 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 10 | ||||
-rwxr-xr-x | services/java/com/android/server/VibratorService.java | 156 |
3 files changed, 163 insertions, 18 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2aaf548..6dfbb2f 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1464,6 +1464,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, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 241d04f..75dcf8c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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(); diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java index de25747..7561b0b 100755 --- a/services/java/com/android/server/VibratorService.java +++ b/services/java/com/android/server/VibratorService.java @@ -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,10 +137,23 @@ 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) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) { @@ -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(); } |