2121import android .content .Intent ;
2222import android .content .IntentFilter ;
2323import android .content .pm .PackageManager ;
24+ import android .database .ContentObserver ;
25+ import android .hardware .input .InputManager ;
2426import android .os .Handler ;
2527import android .os .IVibratorService ;
2628import android .os .PowerManager ;
2931import android .os .IBinder ;
3032import android .os .Binder ;
3133import android .os .SystemClock ;
34+ import android .os .Vibrator ;
3235import android .os .WorkSource ;
36+ import android .provider .Settings ;
37+ import android .provider .Settings .SettingNotFoundException ;
3338import android .util .Slog ;
39+ import android .view .InputDevice ;
3440
41+ import java .util .ArrayList ;
3542import java .util .LinkedList ;
3643import java .util .ListIterator ;
3744
38- public class VibratorService extends IVibratorService .Stub {
45+ public class VibratorService extends IVibratorService .Stub
46+ implements InputManager .InputDeviceListener {
3947 private static final String TAG = "VibratorService" ;
4048
4149 private final LinkedList <Vibration > mVibrations ;
4250 private Vibration mCurrentVibration ;
4351 private final WorkSource mTmpWorkSource = new WorkSource ();
52+ private final Handler mH = new Handler ();
53+
54+ private final Context mContext ;
55+ private final PowerManager .WakeLock mWakeLock ;
56+ private InputManager mIm ;
57+
58+ volatile VibrateThread mThread ;
59+
60+ // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are
61+ // to be acquired
62+ private final ArrayList <Vibrator > mInputDeviceVibrators = new ArrayList <Vibrator >();
63+ private boolean mVibrateInputDevicesSetting ; // guarded by mInputDeviceVibrators
64+ private boolean mInputDeviceListenerRegistered ; // guarded by mInputDeviceVibrators
65+
66+ native static boolean vibratorExists ();
67+ native static void vibratorOn (long milliseconds );
68+ native static void vibratorOff ();
4469
4570 private class Vibration implements IBinder .DeathRecipient {
4671 private final IBinder mToken ;
@@ -112,10 +137,23 @@ public boolean hasLongerTimeout(long millis) {
112137 context .registerReceiver (mIntentReceiver , filter );
113138 }
114139
140+ public void systemReady () {
141+ mIm = (InputManager )mContext .getSystemService (Context .INPUT_SERVICE );
142+ mContext .getContentResolver ().registerContentObserver (
143+ Settings .System .getUriFor (Settings .System .VIBRATE_INPUT_DEVICES ), true ,
144+ new ContentObserver (mH ) {
145+ @ Override
146+ public void onChange (boolean selfChange ) {
147+ updateVibrateInputDevicesSetting ();
148+ }
149+ });
150+ updateVibrateInputDevicesSetting ();
151+ }
152+
115153 public boolean hasVibrator () {
116- return vibratorExists ();
154+ return doVibratorExists ();
117155 }
118-
156+
119157 public void vibrate (long milliseconds , IBinder token ) {
120158 if (mContext .checkCallingOrSelfPermission (android .Manifest .permission .VIBRATE )
121159 != PackageManager .PERMISSION_GRANTED ) {
@@ -131,6 +169,7 @@ public void vibrate(long milliseconds, IBinder token) {
131169 // longer than milliseconds.
132170 return ;
133171 }
172+
134173 Vibration vib = new Vibration (token , milliseconds , uid );
135174 synchronized (mVibrations ) {
136175 removeVibrationLocked (token );
@@ -240,7 +279,7 @@ private void doCancelVibrateLocked() {
240279 }
241280 mThread = null ;
242281 }
243- vibratorOff ();
282+ doVibratorOff ();
244283 mH .removeCallbacks (mVibrationRunnable );
245284 }
246285
@@ -257,7 +296,7 @@ private void startNextVibrationLocked() {
257296 // Lock held on mVibrations
258297 private void startVibrationLocked (final Vibration vib ) {
259298 if (vib .mTimeout != 0 ) {
260- vibratorOn (vib .mTimeout );
299+ doVibratorOn (vib .mTimeout );
261300 mH .postDelayed (mVibrationRunnable , vib .mTimeout );
262301 } else {
263302 // mThread better be null here. doCancelVibrate should always be
@@ -295,6 +334,100 @@ private void unlinkVibration(Vibration vib) {
295334 }
296335 }
297336
337+ private void updateVibrateInputDevicesSetting () {
338+ synchronized (mInputDeviceVibrators ) {
339+ mVibrateInputDevicesSetting = false ;
340+ try {
341+ mVibrateInputDevicesSetting = Settings .System .getInt (mContext .getContentResolver (),
342+ Settings .System .VIBRATE_INPUT_DEVICES ) > 0 ;
343+ } catch (SettingNotFoundException snfe ) {
344+ }
345+
346+ if (mVibrateInputDevicesSetting ) {
347+ if (!mInputDeviceListenerRegistered ) {
348+ mInputDeviceListenerRegistered = true ;
349+ mIm .registerInputDeviceListener (this , mH );
350+ }
351+ } else {
352+ if (mInputDeviceListenerRegistered ) {
353+ mInputDeviceListenerRegistered = false ;
354+ mIm .unregisterInputDeviceListener (this );
355+ }
356+ }
357+
358+ updateInputDeviceVibrators ();
359+ }
360+ }
361+
362+ private void updateInputDeviceVibrators () {
363+ synchronized (mVibrations ) {
364+ doCancelVibrateLocked ();
365+
366+ synchronized (mInputDeviceVibrators ) {
367+ mInputDeviceVibrators .clear ();
368+ if (mVibrateInputDevicesSetting ) {
369+ int [] ids = mIm .getInputDeviceIds ();
370+ for (int i = 0 ; i < ids .length ; i ++) {
371+ InputDevice device = mIm .getInputDevice (ids [i ]);
372+ Vibrator vibrator = device .getVibrator ();
373+ if (vibrator .hasVibrator ()) {
374+ mInputDeviceVibrators .add (vibrator );
375+ }
376+ }
377+ }
378+ }
379+
380+ startNextVibrationLocked ();
381+ }
382+ }
383+
384+ @ Override
385+ public void onInputDeviceAdded (int deviceId ) {
386+ updateInputDeviceVibrators ();
387+ }
388+
389+ @ Override
390+ public void onInputDeviceChanged (int deviceId ) {
391+ updateInputDeviceVibrators ();
392+ }
393+
394+ @ Override
395+ public void onInputDeviceRemoved (int deviceId ) {
396+ updateInputDeviceVibrators ();
397+ }
398+
399+ private boolean doVibratorExists () {
400+ synchronized (mInputDeviceVibrators ) {
401+ return !mInputDeviceVibrators .isEmpty () || vibratorExists ();
402+ }
403+ }
404+
405+ private void doVibratorOn (long millis ) {
406+ synchronized (mInputDeviceVibrators ) {
407+ final int vibratorCount = mInputDeviceVibrators .size ();
408+ if (vibratorCount != 0 ) {
409+ for (int i = 0 ; i < vibratorCount ; i ++) {
410+ mInputDeviceVibrators .get (i ).vibrate (millis );
411+ }
412+ } else {
413+ vibratorOn (millis );
414+ }
415+ }
416+ }
417+
418+ private void doVibratorOff () {
419+ synchronized (mInputDeviceVibrators ) {
420+ final int vibratorCount = mInputDeviceVibrators .size ();
421+ if (vibratorCount != 0 ) {
422+ for (int i = 0 ; i < vibratorCount ; i ++) {
423+ mInputDeviceVibrators .get (i ).cancel ();
424+ }
425+ } else {
426+ vibratorOff ();
427+ }
428+ }
429+ }
430+
298431 private class VibrateThread extends Thread {
299432 final Vibration mVibration ;
300433 boolean mDone ;
@@ -350,7 +483,7 @@ public void run() {
350483 // duration is saved for delay() at top of loop
351484 duration = pattern [index ++];
352485 if (duration > 0 ) {
353- VibratorService .this .vibratorOn (duration );
486+ VibratorService .this .doVibratorOn (duration );
354487 }
355488 } else {
356489 if (repeat < 0 ) {
@@ -394,15 +527,4 @@ public void onReceive(Context context, Intent intent) {
394527 }
395528 }
396529 };
397-
398- private Handler mH = new Handler ();
399-
400- private final Context mContext ;
401- private final PowerManager .WakeLock mWakeLock ;
402-
403- volatile VibrateThread mThread ;
404-
405- native static boolean vibratorExists ();
406- native static void vibratorOn (long milliseconds );
407- native static void vibratorOff ();
408530}
0 commit comments