HID Device: Unregister inactive app
When an app is registered and another app is trying to register, the
first app will automatically be unregistered if it is not visible
Bug: 72168126
Test: manual - register an app, and go to home screen
Change-Id: If4c279f95a10576537dcc4fb5c681c85b2518f1d
(cherry picked from commit cefef42c77577e6fe807db2725ef8b88e7183f02)
diff --git a/android/app/src/com/android/bluetooth/hid/HidDeviceService.java b/android/app/src/com/android/bluetooth/hid/HidDeviceService.java
index 0dfb08d..beba98b 100644
--- a/android/app/src/com/android/bluetooth/hid/HidDeviceService.java
+++ b/android/app/src/com/android/bluetooth/hid/HidDeviceService.java
@@ -16,6 +16,7 @@
package com.android.bluetooth.hid;
+import android.app.ActivityManager;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHidDevice;
import android.bluetooth.BluetoothHidDeviceAppQosSettings;
@@ -23,6 +24,7 @@
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothHidDevice;
import android.bluetooth.IBluetoothHidDeviceCallback;
+import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
@@ -54,6 +56,10 @@
private static final int MESSAGE_SET_PROTOCOL = 5;
private static final int MESSAGE_INTR_DATA = 6;
private static final int MESSAGE_VC_UNPLUG = 7;
+ private static final int MESSAGE_IMPORTANCE_CHANGE = 8;
+
+ private static final int FOREGROUND_IMPORTANCE_CUTOFF =
+ ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
private static HidDeviceService sHidDeviceService;
@@ -65,6 +71,7 @@
private int mUserUid = 0;
private IBluetoothHidDeviceCallback mCallback;
private BluetoothHidDeviceDeathRecipient mDeathRcpt;
+ private ActivityManager mActivityManager;
private HidDeviceServiceHandler mHandler;
@@ -215,9 +222,18 @@
}
mHidDevice = null;
break;
+
+ case MESSAGE_IMPORTANCE_CHANGE:
+ int importance = msg.arg1;
+ int uid = msg.arg2;
+ if (importance > FOREGROUND_IMPORTANCE_CUTOFF
+ && uid >= Process.FIRST_APPLICATION_UID) {
+ unregisterAppUid(uid);
+ }
+ break;
}
}
- };
+ }
private static class BluetoothHidDeviceDeathRecipient implements IBinder.DeathRecipient {
private HidDeviceService mService;
@@ -237,6 +253,17 @@
}
}
+ private ActivityManager.OnUidImportanceListener mUidImportanceListener =
+ new ActivityManager.OnUidImportanceListener() {
+ @Override
+ public void onUidImportance(final int uid, final int importance) {
+ Message message = mHandler.obtainMessage(MESSAGE_IMPORTANCE_CHANGE);
+ message.arg1 = importance;
+ message.arg2 = uid;
+ mHandler.sendMessage(message);
+ }
+ };
+
@VisibleForTesting
static class BluetoothHidDeviceBinder extends IBluetoothHidDevice.Stub
implements IProfileServiceBinder {
@@ -458,10 +485,16 @@
return false;
}
- mUserUid = Binder.getCallingUid();
+ int callingUid = Binder.getCallingUid();
if (DBG) {
- Log.d(TAG, "registerApp(): calling uid=" + mUserUid);
+ Log.d(TAG, "registerApp(): calling uid=" + callingUid);
}
+ if (callingUid >= Process.FIRST_APPLICATION_UID
+ && mActivityManager.getUidImportance(callingUid) > FOREGROUND_IMPORTANCE_CUTOFF) {
+ Log.w(TAG, "registerApp(): failed because the app is not foreground");
+ return false;
+ }
+ mUserUid = callingUid;
mCallback = callback;
return mHidDeviceNativeInterface.registerApp(sdp.name, sdp.description, sdp.provider,
@@ -475,11 +508,21 @@
}
int callingUid = Binder.getCallingUid();
- if (callingUid == mUserUid || callingUid < Process.FIRST_APPLICATION_UID) {
+ return unregisterAppUid(callingUid);
+ }
+
+ private synchronized boolean unregisterAppUid(int uid) {
+ if (DBG) {
+ Log.d(TAG, "unregisterAppUid(): uid=" + uid);
+ }
+
+ if (uid == mUserUid || uid < Process.FIRST_APPLICATION_UID) {
mUserUid = 0;
return mHidDeviceNativeInterface.unregisterApp();
}
- Log.w(TAG, "unregisterApp(): caller UID doesn't match user UID");
+ if (DBG) {
+ Log.d(TAG, "unregisterAppUid(): caller UID doesn't match user UID");
+ }
return false;
}
@@ -547,10 +590,13 @@
}
mHandler = new HidDeviceServiceHandler();
- setHidDeviceService(this);
mHidDeviceNativeInterface = HidDeviceNativeInterface.getInstance();
mHidDeviceNativeInterface.init();
mNativeAvailable = true;
+ mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ mActivityManager.addOnUidImportanceListener(mUidImportanceListener,
+ FOREGROUND_IMPORTANCE_CUTOFF);
+ setHidDeviceService(this);
return true;
}
@@ -559,21 +605,14 @@
if (DBG) {
Log.d(TAG, "stop()");
}
- return true;
- }
- @Override
- protected void cleanup() {
- if (DBG) {
- Log.d(TAG, "cleanup()");
- }
-
+ setHidDeviceService(null);
if (mNativeAvailable) {
mHidDeviceNativeInterface.cleanup();
mNativeAvailable = false;
}
- // TODO(b/72948646): should be moved to stop()
- setHidDeviceService(null);
+ mActivityManager.removeOnUidImportanceListener(mUidImportanceListener);
+ return true;
}
@Override
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java
index af192fb..618d2b4 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java
@@ -117,13 +117,6 @@
mHidDeviceService = HidDeviceService.getHidDeviceService();
Assert.assertNotNull(mHidDeviceService);
- InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mHidDeviceService.start();
- }
- });
-
// Force unregister app first
mHidDeviceService.unregisterApp();