Skip to content

Commit 90aba7c

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Add support for input devices that have vibrators."
2 parents 21e09bc + a47425a commit 90aba7c

File tree

15 files changed

+589
-7
lines changed

15 files changed

+589
-7
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22362,6 +22362,7 @@ package android.view {
2236222362
method public java.util.List<android.view.InputDevice.MotionRange> getMotionRanges();
2236322363
method public java.lang.String getName();
2236422364
method public int getSources();
22365+
method public android.os.Vibrator getVibrator();
2236522366
method public boolean isVirtual();
2236622367
method public void writeToParcel(android.os.Parcel, int);
2236722368
field public static final android.os.Parcelable.Creator CREATOR;

core/java/android/hardware/input/IInputManager.aidl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package android.hardware.input;
1818

1919
import android.hardware.input.KeyboardLayout;
2020
import android.hardware.input.IInputDevicesChangedListener;
21+
import android.os.IBinder;
2122
import android.view.InputDevice;
2223
import android.view.InputEvent;
2324

@@ -46,4 +47,8 @@ interface IInputManager {
4647

4748
// Registers an input devices changed listener.
4849
void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
50+
51+
// Input device vibrator control.
52+
void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
53+
void cancelVibrate(int deviceId, IBinder token);
4954
}

core/java/android/hardware/input/InputManager.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
import android.annotation.SdkConstant;
2020
import android.annotation.SdkConstant.SdkConstantType;
2121
import android.content.Context;
22+
import android.os.Binder;
2223
import android.os.Handler;
2324
import android.os.IBinder;
2425
import android.os.Looper;
2526
import android.os.Message;
2627
import android.os.RemoteException;
2728
import android.os.ServiceManager;
29+
import android.os.Vibrator;
2830
import android.provider.Settings;
2931
import android.provider.Settings.SettingNotFoundException;
3032
import android.util.Log;
@@ -586,6 +588,15 @@ private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceI
586588
return false;
587589
}
588590

591+
/**
592+
* Gets a vibrator service associated with an input device, assuming it has one.
593+
* @return The vibrator, never null.
594+
* @hide
595+
*/
596+
public Vibrator getInputDeviceVibrator(int deviceId) {
597+
return new InputDeviceVibrator(deviceId);
598+
}
599+
589600
/**
590601
* Listens for changes in input devices.
591602
*/
@@ -645,4 +656,45 @@ public void handleMessage(Message msg) {
645656
}
646657
}
647658
}
659+
660+
private final class InputDeviceVibrator extends Vibrator {
661+
private final int mDeviceId;
662+
private final Binder mToken;
663+
664+
public InputDeviceVibrator(int deviceId) {
665+
mDeviceId = deviceId;
666+
mToken = new Binder();
667+
}
668+
669+
@Override
670+
public boolean hasVibrator() {
671+
return true;
672+
}
673+
674+
@Override
675+
public void vibrate(long milliseconds) {
676+
vibrate(new long[] { 0, milliseconds}, -1);
677+
}
678+
679+
@Override
680+
public void vibrate(long[] pattern, int repeat) {
681+
if (repeat >= pattern.length) {
682+
throw new ArrayIndexOutOfBoundsException();
683+
}
684+
try {
685+
mIm.vibrate(mDeviceId, pattern, repeat, mToken);
686+
} catch (RemoteException ex) {
687+
Log.w(TAG, "Failed to vibrate.", ex);
688+
}
689+
}
690+
691+
@Override
692+
public void cancel() {
693+
try {
694+
mIm.cancelVibrate(mDeviceId, mToken);
695+
} catch (RemoteException ex) {
696+
Log.w(TAG, "Failed to cancel vibration.", ex);
697+
}
698+
}
699+
}
648700
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package android.os;
18+
19+
import android.util.Log;
20+
21+
/**
22+
* Vibrator implementation that does nothing.
23+
*
24+
* @hide
25+
*/
26+
public class NullVibrator extends Vibrator {
27+
private static final NullVibrator sInstance = new NullVibrator();
28+
29+
private NullVibrator() {
30+
}
31+
32+
public static NullVibrator getInstance() {
33+
return sInstance;
34+
}
35+
36+
@Override
37+
public boolean hasVibrator() {
38+
return false;
39+
}
40+
41+
@Override
42+
public void vibrate(long milliseconds) {
43+
}
44+
45+
@Override
46+
public void vibrate(long[] pattern, int repeat) {
47+
if (repeat >= pattern.length) {
48+
throw new ArrayIndexOutOfBoundsException();
49+
}
50+
}
51+
52+
@Override
53+
public void cancel() {
54+
}
55+
}

core/java/android/view/InputDevice.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616

1717
package android.view;
1818

19+
import android.content.Context;
1920
import android.hardware.input.InputManager;
2021
import android.os.Parcel;
2122
import android.os.Parcelable;
23+
import android.os.Vibrator;
24+
import android.os.NullVibrator;
2225

2326
import java.util.ArrayList;
2427
import java.util.List;
@@ -46,8 +49,11 @@ public final class InputDevice implements Parcelable {
4649
private final int mSources;
4750
private final int mKeyboardType;
4851
private final KeyCharacterMap mKeyCharacterMap;
52+
private final boolean mHasVibrator;
4953
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
5054

55+
private Vibrator mVibrator; // guarded by mMotionRanges during initialization
56+
5157
/**
5258
* A mask for input source classes.
5359
*
@@ -304,14 +310,15 @@ public InputDevice[] newArray(int size) {
304310

305311
// Called by native code.
306312
private InputDevice(int id, int generation, String name, String descriptor, int sources,
307-
int keyboardType, KeyCharacterMap keyCharacterMap) {
313+
int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator) {
308314
mId = id;
309315
mGeneration = generation;
310316
mName = name;
311317
mDescriptor = descriptor;
312318
mSources = sources;
313319
mKeyboardType = keyboardType;
314320
mKeyCharacterMap = keyCharacterMap;
321+
mHasVibrator = hasVibrator;
315322
}
316323

317324
private InputDevice(Parcel in) {
@@ -322,6 +329,7 @@ private InputDevice(Parcel in) {
322329
mSources = in.readInt();
323330
mKeyboardType = in.readInt();
324331
mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
332+
mHasVibrator = in.readInt() != 0;
325333

326334
for (;;) {
327335
int axis = in.readInt();
@@ -521,6 +529,31 @@ private void addMotionRange(int axis, int source,
521529
mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz));
522530
}
523531

532+
/**
533+
* Gets the vibrator service associated with the device, if there is one.
534+
* Even if the device does not have a vibrator, the result is never null.
535+
* Use {@link Vibrator#hasVibrator} to determine whether a vibrator is
536+
* present.
537+
*
538+
* Note that the vibrator associated with the device may be different from
539+
* the system vibrator. To obtain an instance of the system vibrator instead, call
540+
* {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as argument.
541+
*
542+
* @return The vibrator service associated with the device, never null.
543+
*/
544+
public Vibrator getVibrator() {
545+
synchronized (mMotionRanges) {
546+
if (mVibrator == null) {
547+
if (mHasVibrator) {
548+
mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);
549+
} else {
550+
mVibrator = NullVibrator.getInstance();
551+
}
552+
}
553+
return mVibrator;
554+
}
555+
}
556+
524557
/**
525558
* Provides information about the range of values for a particular {@link MotionEvent} axis.
526559
*
@@ -617,6 +650,7 @@ public void writeToParcel(Parcel out, int flags) {
617650
out.writeInt(mSources);
618651
out.writeInt(mKeyboardType);
619652
mKeyCharacterMap.writeToParcel(out, flags);
653+
out.writeInt(mHasVibrator ? 1 : 0);
620654

621655
final int numRanges = mMotionRanges.size();
622656
for (int i = 0; i < numRanges; i++) {
@@ -657,6 +691,8 @@ public String toString() {
657691
}
658692
description.append("\n");
659693

694+
description.append(" Has Vibrator: ").append(mHasVibrator).append("\n");
695+
660696
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
661697
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
662698
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");

core/jni/android_view_InputDevice.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
5757
gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(),
5858
nameObj.get(), descriptorObj.get(),
5959
deviceInfo.getSources(), deviceInfo.getKeyboardType(),
60-
kcmObj.get()));
60+
kcmObj.get(), deviceInfo.hasVibrator()));
6161

6262
const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
6363
for (size_t i = 0; i < ranges.size(); i++) {
@@ -87,7 +87,7 @@ int register_android_view_InputDevice(JNIEnv* env)
8787
gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
8888

8989
GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
90-
"<init>", "(IILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;)V");
90+
"<init>", "(IILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;Z)V");
9191

9292
GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
9393
"addMotionRange", "(IIFFFF)V");

include/androidfw/InputDevice.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class InputDeviceInfo {
9393
return mKeyCharacterMap;
9494
}
9595

96+
inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
97+
inline bool hasVibrator() const { return mHasVibrator; }
98+
9699
inline const Vector<MotionRange>& getMotionRanges() const {
97100
return mMotionRanges;
98101
}
@@ -105,6 +108,7 @@ class InputDeviceInfo {
105108
uint32_t mSources;
106109
int32_t mKeyboardType;
107110
sp<KeyCharacterMap> mKeyCharacterMap;
111+
bool mHasVibrator;
108112

109113
Vector<MotionRange> mMotionRanges;
110114
};

libs/androidfw/InputDevice.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
136136
mSources(other.mSources),
137137
mKeyboardType(other.mKeyboardType),
138138
mKeyCharacterMap(other.mKeyCharacterMap),
139+
mHasVibrator(other.mHasVibrator),
139140
mMotionRanges(other.mMotionRanges) {
140141
}
141142

@@ -150,6 +151,7 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation,
150151
mDescriptor = descriptor;
151152
mSources = 0;
152153
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
154+
mHasVibrator = false;
153155
mMotionRanges.clear();
154156
}
155157

0 commit comments

Comments
 (0)