Skip to content

Commit 5bbd4b4

Browse files
author
Jeff Brown
committed
Get alias for Bluetooth devices.
Bluetooth devices can be renamed by the user. Make the input system aware of the user-specified name and transparently pass it down to applications. This enables the keyboard layout picker Settings UI to use device names that are consistent with what the user set in the Bluetooth UI. Bug: 6363157 Change-Id: I8eea26ce2c69c2a3f09c8de02e9e847610e0419c
1 parent 9e6d4b0 commit 5bbd4b4

File tree

11 files changed

+127
-30
lines changed

11 files changed

+127
-30
lines changed

core/java/android/bluetooth/BluetoothDevice.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ public final class BluetoothDevice implements Parcelable {
159159
public static final String ACTION_NAME_CHANGED =
160160
"android.bluetooth.device.action.NAME_CHANGED";
161161

162+
/**
163+
* Broadcast Action: Indicates the alias of a remote device has been
164+
* changed.
165+
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
166+
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
167+
*
168+
* @hide
169+
*/
170+
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
171+
public static final String ACTION_ALIAS_CHANGED =
172+
"android.bluetooth.device.action.ALIAS_CHANGED";
173+
162174
/**
163175
* Broadcast Action: Indicates a change in the bond state of a remote
164176
* device. For example, if a device is bonded (paired).

core/java/android/server/BluetoothEventLoop.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,10 @@ private void onDevicePropertyChanged(String deviceObjectPath, String[] propValue
405405
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
406406
} else if (name.equals("Alias")) {
407407
mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
408+
Intent intent = new Intent(BluetoothDevice.ACTION_ALIAS_CHANGED);
409+
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
410+
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
411+
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
408412
} else if (name.equals("Class")) {
409413
mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
410414
Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED);

core/jni/android_view_InputDevice.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ static struct {
3535
} gInputDeviceClassInfo;
3636

3737
jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo) {
38-
ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getName().string()));
38+
ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getDisplayName().string()));
3939
if (!nameObj.get()) {
4040
return NULL;
4141
}
4242

4343
ScopedLocalRef<jstring> descriptorObj(env,
44-
env->NewStringUTF(deviceInfo.getDescriptor().string()));
44+
env->NewStringUTF(deviceInfo.getIdentifier().descriptor.string()));
4545
if (!descriptorObj.get()) {
4646
return NULL;
4747
}

include/androidfw/InputDevice.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,16 @@ class InputDeviceInfo {
6666
float fuzz;
6767
};
6868

69-
void initialize(int32_t id, int32_t generation,
70-
const String8& name, const String8& descriptor);
69+
void initialize(int32_t id, int32_t generation, const InputDeviceIdentifier& identifier,
70+
const String8& alias);
7171

7272
inline int32_t getId() const { return mId; }
7373
inline int32_t getGeneration() const { return mGeneration; }
74-
inline const String8 getName() const { return mName; }
75-
inline const String8 getDescriptor() const { return mDescriptor; }
74+
inline const InputDeviceIdentifier& getIdentifier() const { return mIdentifier; }
75+
inline const String8& getAlias() const { return mAlias; }
76+
inline const String8& getDisplayName() const {
77+
return mAlias.isEmpty() ? mIdentifier.name : mAlias;
78+
}
7679
inline uint32_t getSources() const { return mSources; }
7780

7881
const MotionRange* getMotionRange(int32_t axis, uint32_t source) const;
@@ -103,8 +106,8 @@ class InputDeviceInfo {
103106
private:
104107
int32_t mId;
105108
int32_t mGeneration;
106-
String8 mName;
107-
String8 mDescriptor;
109+
InputDeviceIdentifier mIdentifier;
110+
String8 mAlias;
108111
uint32_t mSources;
109112
int32_t mKeyboardType;
110113
sp<KeyCharacterMap> mKeyCharacterMap;

libs/androidfw/InputDevice.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,11 @@ String8 getInputDeviceConfigurationFilePathByName(
127127
// --- InputDeviceInfo ---
128128

129129
InputDeviceInfo::InputDeviceInfo() {
130-
initialize(-1, -1, String8("uninitialized device info"), String8("unknown"));
130+
initialize(-1, -1, InputDeviceIdentifier(), String8());
131131
}
132132

133133
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
134-
mId(other.mId), mGeneration(other.mGeneration),
135-
mName(other.mName), mDescriptor(other.mDescriptor),
134+
mId(other.mId), mGeneration(other.mGeneration), mIdentifier(other.mIdentifier),
136135
mSources(other.mSources),
137136
mKeyboardType(other.mKeyboardType),
138137
mKeyCharacterMap(other.mKeyCharacterMap),
@@ -144,11 +143,11 @@ InputDeviceInfo::~InputDeviceInfo() {
144143
}
145144

146145
void InputDeviceInfo::initialize(int32_t id, int32_t generation,
147-
const String8& name, const String8& descriptor) {
146+
const InputDeviceIdentifier& identifier, const String8& alias) {
148147
mId = id;
149148
mGeneration = generation;
150-
mName = name;
151-
mDescriptor = descriptor;
149+
mIdentifier = identifier;
150+
mAlias = alias;
152151
mSources = 0;
153152
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
154153
mHasVibrator = false;

services/input/InputReader.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ void InputDevice::dump(String8& dump) {
918918
getDeviceInfo(& deviceInfo);
919919

920920
dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
921-
deviceInfo.getName().string());
921+
deviceInfo.getDisplayName().string());
922922
dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
923923
dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
924924
dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
@@ -972,6 +972,16 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config
972972
}
973973
}
974974

975+
if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
976+
if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
977+
String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
978+
if (mAlias != alias) {
979+
mAlias = alias;
980+
bumpGeneration();
981+
}
982+
}
983+
}
984+
975985
size_t numMappers = mMappers.size();
976986
for (size_t i = 0; i < numMappers; i++) {
977987
InputMapper* mapper = mMappers[i];
@@ -1039,7 +1049,7 @@ void InputDevice::timeoutExpired(nsecs_t when) {
10391049
}
10401050

10411051
void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
1042-
outDeviceInfo->initialize(mId, mGeneration, mIdentifier.name, mIdentifier.descriptor);
1052+
outDeviceInfo->initialize(mId, mGeneration, mIdentifier, mAlias);
10431053

10441054
size_t numMappers = mMappers.size();
10451055
for (size_t i = 0; i < numMappers; i++) {

services/input/InputReader.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ struct InputReaderConfiguration {
7070
// The keyboard layouts must be reloaded.
7171
CHANGE_KEYBOARD_LAYOUTS = 1 << 4,
7272

73+
// The device name alias supplied by the may have changed for some devices.
74+
CHANGE_DEVICE_ALIAS = 1 << 5,
75+
7376
// All devices must be reopened.
7477
CHANGE_MUST_REOPEN = 1 << 31,
7578
};
@@ -228,6 +231,9 @@ class InputReaderPolicyInterface : public virtual RefBase {
228231

229232
/* Gets the keyboard layout for a particular input device. */
230233
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) = 0;
234+
235+
/* Gets a user-supplied alias for a particular input device, or an empty string if none. */
236+
virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
231237
};
232238

233239

@@ -528,6 +534,7 @@ class InputDevice {
528534
int32_t mId;
529535
int32_t mGeneration;
530536
InputDeviceIdentifier mIdentifier;
537+
String8 mAlias;
531538
uint32_t mClasses;
532539

533540
Vector<InputMapper*> mMappers;

services/input/tests/InputReader_test.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ class FakeInputReaderPolicy : public InputReaderPolicyInterface {
174174
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) {
175175
return NULL;
176176
}
177+
178+
virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) {
179+
return String8::empty();
180+
}
177181
};
178182

179183

@@ -1081,7 +1085,7 @@ TEST_F(InputReaderTest, GetInputDevices) {
10811085

10821086
ASSERT_EQ(1U, inputDevices.size());
10831087
ASSERT_EQ(1, inputDevices[0].getId());
1084-
ASSERT_STREQ("keyboard", inputDevices[0].getName().string());
1088+
ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
10851089
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
10861090
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
10871091
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
@@ -1090,7 +1094,7 @@ TEST_F(InputReaderTest, GetInputDevices) {
10901094
inputDevices = mFakePolicy->getInputDevices();
10911095
ASSERT_EQ(1U, inputDevices.size());
10921096
ASSERT_EQ(1, inputDevices[0].getId());
1093-
ASSERT_STREQ("keyboard", inputDevices[0].getName().string());
1097+
ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
10941098
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
10951099
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
10961100
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
@@ -1311,7 +1315,7 @@ TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
13111315
InputDeviceInfo info;
13121316
mDevice->getDeviceInfo(&info);
13131317
ASSERT_EQ(DEVICE_ID, info.getId());
1314-
ASSERT_STREQ(DEVICE_NAME, info.getName().string());
1318+
ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
13151319
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
13161320
ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
13171321

@@ -1381,7 +1385,7 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe
13811385
InputDeviceInfo info;
13821386
mDevice->getDeviceInfo(&info);
13831387
ASSERT_EQ(DEVICE_ID, info.getId());
1384-
ASSERT_STREQ(DEVICE_NAME, info.getName().string());
1388+
ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
13851389
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
13861390
ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
13871391

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ public void run() {
726726
final StatusBarManagerService statusBarF = statusBar;
727727
final DreamManagerService dreamyF = dreamy;
728728
final InputManagerService inputManagerF = inputManager;
729+
final BluetoothService bluetoothF = bluetooth;
729730

730731
// We now tell the activity manager it is okay to run third party
731732
// code. It will call back into us once it has gotten to the state
@@ -838,7 +839,7 @@ public void run() {
838839
reportWtf("making DreamManagerService ready", e);
839840
}
840841
try {
841-
if (inputManagerF != null) inputManagerF.systemReady();
842+
if (inputManagerF != null) inputManagerF.systemReady(bluetoothF);
842843
} catch (Throwable e) {
843844
reportWtf("making InputManagerService ready", e);
844845
}

services/java/com/android/server/input/InputManagerService.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.xmlpull.v1.XmlSerializer;
2727

2828
import android.Manifest;
29+
import android.bluetooth.BluetoothAdapter;
30+
import android.bluetooth.BluetoothDevice;
2931
import android.content.BroadcastReceiver;
3032
import android.content.ComponentName;
3133
import android.content.Context;
@@ -56,6 +58,7 @@
5658
import android.os.RemoteException;
5759
import android.provider.Settings;
5860
import android.provider.Settings.SettingNotFoundException;
61+
import android.server.BluetoothService;
5962
import android.util.Log;
6063
import android.util.Slog;
6164
import android.util.SparseArray;
@@ -106,6 +109,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
106109
private final Callbacks mCallbacks;
107110
private final InputManagerHandler mHandler;
108111
private boolean mSystemReady;
112+
private BluetoothService mBluetoothService;
109113

110114
// Persistent data store. Must be locked each time during use.
111115
private final PersistentDataStore mDataStore = new PersistentDataStore();
@@ -167,6 +171,7 @@ private static native void nativeVibrate(int ptr, int deviceId, long[] pattern,
167171
int repeat, int token);
168172
private static native void nativeCancelVibrate(int ptr, int deviceId, int token);
169173
private static native void nativeReloadKeyboardLayouts(int ptr);
174+
private static native void nativeReloadDeviceAliases(int ptr);
170175
private static native String nativeDump(int ptr);
171176
private static native void nativeMonitor(int ptr);
172177

@@ -217,12 +222,12 @@ public void start() {
217222
updateShowTouchesFromSettings();
218223
}
219224

220-
public void systemReady() {
225+
public void systemReady(BluetoothService bluetoothService) {
221226
if (DEBUG) {
222227
Slog.d(TAG, "System ready.");
223228
}
229+
mBluetoothService = bluetoothService;
224230
mSystemReady = true;
225-
reloadKeyboardLayouts();
226231

227232
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
228233
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -237,12 +242,30 @@ public void onReceive(Context context, Intent intent) {
237242
reloadKeyboardLayouts();
238243
}
239244
}, filter, null, mHandler);
245+
246+
filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
247+
mContext.registerReceiver(new BroadcastReceiver() {
248+
@Override
249+
public void onReceive(Context context, Intent intent) {
250+
if (DEBUG) {
251+
Slog.d(TAG, "Bluetooth alias changed, reloading device names.");
252+
}
253+
reloadDeviceAliases();
254+
}
255+
}, filter, null, mHandler);
256+
257+
reloadKeyboardLayouts();
258+
reloadDeviceAliases();
240259
}
241260

242261
private void reloadKeyboardLayouts() {
243262
nativeReloadKeyboardLayouts(mPtr);
244263
}
245264

265+
private void reloadDeviceAliases() {
266+
nativeReloadDeviceAliases(mPtr);
267+
}
268+
246269
public void setDisplaySize(int displayId, int width, int height,
247270
int externalWidth, int externalHeight) {
248271
if (width <= 0 || height <= 0 || externalWidth <= 0 || externalHeight <= 0) {
@@ -1121,6 +1144,15 @@ public void visitKeyboardLayout(Resources resources,
11211144
return result;
11221145
}
11231146

1147+
// Native callback.
1148+
private String getDeviceAlias(String uniqueId) {
1149+
if (mBluetoothService != null &&
1150+
BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
1151+
return mBluetoothService.getRemoteAlias(uniqueId);
1152+
}
1153+
return null;
1154+
}
1155+
11241156

11251157
/**
11261158
* Callback interface implemented by the Window Manager.

0 commit comments

Comments
 (0)