Skip to content

Commit 9688fea

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Add setting to redirect vibrator to game controller."
2 parents 75bf744 + 7f6c231 commit 9688fea

File tree

3 files changed

+163
-18
lines changed

3 files changed

+163
-18
lines changed

core/java/android/provider/Settings.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,20 @@ public static void setShowGTalkServiceStatus(ContentResolver cr, boolean flag) {
14631463
*/
14641464
public static final String VIBRATE_ON = "vibrate_on";
14651465

1466+
/**
1467+
* If 1, redirects the system vibrator to all currently attached input devices
1468+
* that support vibration. If there are no such input devices, then the system
1469+
* vibrator is used instead.
1470+
* If 0, does not register the system vibrator.
1471+
*
1472+
* This setting is mainly intended to provide a compatibility mechanism for
1473+
* applications that only know about the system vibrator and do not use the
1474+
* input device vibrator API.
1475+
*
1476+
* @hide
1477+
*/
1478+
public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices";
1479+
14661480
/**
14671481
* Ringer volume. This is used internally, changing this value will not
14681482
* change the volume. See AudioManager.
@@ -1970,6 +1984,7 @@ public static void setShowGTalkServiceStatus(ContentResolver cr, boolean flag) {
19701984
SCREEN_BRIGHTNESS_MODE,
19711985
SCREEN_AUTO_BRIGHTNESS_ADJ,
19721986
VIBRATE_ON,
1987+
VIBRATE_INPUT_DEVICES,
19731988
MODE_RINGER,
19741989
MODE_RINGER_STREAMS_AFFECTED,
19751990
MUTE_STREAMS_AFFECTED,

services/java/com/android/server/SystemServer.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public void run() {
115115
LightsService lights = null;
116116
PowerManagerService power = null;
117117
BatteryService battery = null;
118+
VibratorService vibrator = null;
118119
AlarmManagerService alarm = null;
119120
NetworkManagementService networkManagement = null;
120121
NetworkStatsService networkStats = null;
@@ -203,7 +204,8 @@ public void run() {
203204
ServiceManager.addService("battery", battery);
204205

205206
Slog.i(TAG, "Vibrator Service");
206-
ServiceManager.addService("vibrator", new VibratorService(context));
207+
vibrator = new VibratorService(context);
208+
ServiceManager.addService("vibrator", vibrator);
207209

208210
// only initialize the power service after we have started the
209211
// lights service, content providers and the battery service.
@@ -645,6 +647,12 @@ public void run() {
645647

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

650+
try {
651+
vibrator.systemReady();
652+
} catch (Throwable e) {
653+
reportWtf("making Vibrator Service ready", e);
654+
}
655+
648656
if (devicePolicy != null) {
649657
try {
650658
devicePolicy.systemReady();

services/java/com/android/server/VibratorService.java

Lines changed: 139 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import android.content.Intent;
2222
import android.content.IntentFilter;
2323
import android.content.pm.PackageManager;
24+
import android.database.ContentObserver;
25+
import android.hardware.input.InputManager;
2426
import android.os.Handler;
2527
import android.os.IVibratorService;
2628
import android.os.PowerManager;
@@ -29,18 +31,41 @@
2931
import android.os.IBinder;
3032
import android.os.Binder;
3133
import android.os.SystemClock;
34+
import android.os.Vibrator;
3235
import android.os.WorkSource;
36+
import android.provider.Settings;
37+
import android.provider.Settings.SettingNotFoundException;
3338
import android.util.Slog;
39+
import android.view.InputDevice;
3440

41+
import java.util.ArrayList;
3542
import java.util.LinkedList;
3643
import 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

Comments
 (0)