summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-04-13 20:38:38 -0700
committerJeff Brown <jeffbrown@google.com>2012-04-13 20:38:38 -0700
commit7f6c231a76f0bedaf9655a24707737d343244312 (patch)
tree63eaaa6255f04d34dd125da1459d2b2e70753002
parent90aba7caac78b407347b930cfb6ff7d6658ac90a (diff)
downloadframeworks_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.java15
-rw-r--r--services/java/com/android/server/SystemServer.java10
-rwxr-xr-xservices/java/com/android/server/VibratorService.java156
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();
}