Loading core/java/com/android/internal/infra/ServiceConnector.java +39 −0 Original line number Diff line number Diff line Loading @@ -726,4 +726,43 @@ public interface ServiceConnector<I extends IInterface> { } } } /** * A {@link ServiceConnector} that doesn't connect to anything. * * @param <T> the type of the {@link IInterface ipc interface} for the remote service */ class NoOp<T extends IInterface> extends AndroidFuture<Object> implements ServiceConnector<T> { { completeExceptionally(new IllegalStateException("ServiceConnector is a no-op")); } @Override public boolean run(@NonNull VoidJob<T> job) { return false; } @Override public AndroidFuture<Void> post(@NonNull VoidJob<T> job) { return (AndroidFuture) this; } @Override public <R> AndroidFuture<R> postForResult(@NonNull Job<T, R> job) { return (AndroidFuture) this; } @Override public <R> AndroidFuture<R> postAsync(@NonNull Job<T, CompletableFuture<R>> job) { return (AndroidFuture) this; } @Override public AndroidFuture<T> connect() { return (AndroidFuture) this; } @Override public void unbind() {} } } services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +105 −25 Original line number Diff line number Diff line Loading @@ -20,8 +20,11 @@ package com.android.server.companion; import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES; import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED; import static android.content.Context.BIND_IMPORTANT; import static android.content.pm.PackageManager.MATCH_ALL; import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.CollectionUtils.emptyIfNull; import static com.android.internal.util.CollectionUtils.filter; import static com.android.internal.util.CollectionUtils.find; import static com.android.internal.util.CollectionUtils.forEach; import static com.android.internal.util.CollectionUtils.map; Loading @@ -45,6 +48,7 @@ import android.app.PendingIntent; import android.app.role.RoleManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; Loading @@ -58,15 +62,18 @@ import android.companion.ICompanionDeviceDiscoveryService; import android.companion.ICompanionDeviceManager; import android.companion.ICompanionDeviceService; import android.companion.IFindDeviceCallback; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.NetworkPolicyManager; import android.os.Binder; Loading Loading @@ -189,6 +196,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener = new BluetoothDeviceConnectedListener(); private BleStateBroadcastReceiver mBleStateBroadcastReceiver = new BleStateBroadcastReceiver(); private List<String> mCurrentlyConnectedDevices = new ArrayList<>(); private ArrayMap<String, Date> mDevicesLastNearby = new ArrayMap<>(); private UnbindDeviceListenersRunnable Loading Loading @@ -286,11 +294,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public void onBootPhase(int phase) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { // Init Bluetooth mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter != null) { mBluetoothAdapter.registerBluetoothConnectionCallback( getContext().getMainExecutor(), mBluetoothDeviceConnectedListener); getContext().registerReceiver( mBleStateBroadcastReceiver, mBleStateBroadcastReceiver.mIntentFilter); initBleScanning(); } else { Log.w(LOG_TAG, "No BluetoothAdapter available"); Loading Loading @@ -553,7 +564,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return true; } return CollectionUtils.any( return any( getAllAssociations(userId, packageName), a -> Objects.equals(a.getDeviceMacAddress(), macAddress)); } Loading Loading @@ -604,6 +615,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return association; } })); restartBleScan(); } private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { Loading Loading @@ -917,7 +930,12 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private List<UserInfo> getAllUsers() { return getContext().getSystemService(UserManager.class).getUsers(); long identity = Binder.clearCallingIdentity(); try { return mUserManager.getUsers(); } finally { Binder.restoreCallingIdentity(identity); } } private Set<Association> getAllAssociations(int userId, @Nullable String packageFilter) { Loading @@ -927,11 +945,16 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private Set<Association> getAllAssociations() { long identity = Binder.clearCallingIdentity(); try { ArraySet<Association> result = new ArraySet<>(); for (UserInfo user : mUserManager.getAliveUsers()) { result.addAll(getAllAssociations(user.id)); } return result; } finally { Binder.restoreCallingIdentity(identity); } } Loading Loading @@ -1029,11 +1052,28 @@ public class CompanionDeviceManagerService extends SystemService implements Bind Association a) { return mDeviceListenerServiceConnectors.forUser(a.getUserId()).computeIfAbsent( a.getPackageName(), pkg -> new ServiceConnector.Impl<>(getContext(), new Intent(CompanionDeviceService.SERVICE_INTERFACE), pkg -> createDeviceListenerServiceConnector(a)); } private ServiceConnector<ICompanionDeviceService> createDeviceListenerServiceConnector( Association a) { List<ResolveInfo> resolveInfos = getContext().getPackageManager().queryIntentServicesAsUser( new Intent(CompanionDeviceService.SERVICE_INTERFACE), MATCH_ALL, a.getUserId()); List<ResolveInfo> packageResolveInfos = filter(resolveInfos, info -> Objects.equals(info.serviceInfo.packageName, a.getPackageName())); if (packageResolveInfos.size() != 1) { Log.w(LOG_TAG, "Device presence listener package must have exactly one " + "CompanionDeviceService, but " + a.getPackageName() + " has " + packageResolveInfos.size()); return new ServiceConnector.NoOp<>(); } ComponentName componentName = packageResolveInfos.get(0).serviceInfo.getComponentName(); Log.i(LOG_TAG, "Initializing CompanionDeviceService binding for " + componentName); return new ServiceConnector.Impl<>(getContext(), new Intent(CompanionDeviceService.SERVICE_INTERFACE).setComponent(componentName), BIND_IMPORTANT, a.getUserId(), ICompanionDeviceService.Stub::asInterface)); ICompanionDeviceService.Stub::asInterface); } private class BleScanCallback extends ScanCallback { Loading @@ -1059,8 +1099,34 @@ public class CompanionDeviceManagerService extends SystemService implements Bind if (errorCode == SCAN_FAILED_ALREADY_STARTED) { // ignore - this might happen if BT tries to auto-restore scans for us in the // future Log.i(LOG_TAG, "Ignoring BLE scan error: SCAN_FAILED_ALREADY_STARTED"); } else { Log.wtf(LOG_TAG, "Failed to start BLE scan: error " + errorCode); Log.w(LOG_TAG, "Failed to start BLE scan: error " + errorCode); } } } private class BleStateBroadcastReceiver extends BroadcastReceiver { final IntentFilter mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); @Override public void onReceive(Context context, Intent intent) { int previousState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, -1); int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); Log.i(LOG_TAG, "Received BT state transition broadcast: " + BluetoothAdapter.nameForState(previousState) + " -> " + BluetoothAdapter.nameForState(newState)); boolean bleOn = newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_BLE_ON; if (bleOn) { if (mBluetoothAdapter.getBluetoothLeScanner() != null) { startBleScan(); } else { Log.wtf(LOG_TAG, "BLE on, but BluetoothLeScanner == null"); } } } } Loading Loading @@ -1125,7 +1191,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private void onDeviceNearby(String address) { Date timestamp = new Date(); mDevicesLastNearby.put(address, timestamp); Date oldTimestamp = mDevicesLastNearby.put(address, timestamp); cancelUnbindDeviceListener(address); Loading @@ -1133,6 +1199,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind .computeIfAbsent(address, addr -> new TriggerDeviceDisappearedRunnable(address)) .schedule(); // Avoid spamming the app if device is already known to be nearby boolean justAppeared = oldTimestamp == null || timestamp.getTime() - oldTimestamp.getTime() >= DEVICE_DISAPPEARED_TIMEOUT_MS; if (justAppeared) { for (Association association : getAllAssociations(address)) { if (association.isNotifyOnDeviceNearby()) { if (DEBUG) { Loading @@ -1145,6 +1215,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } } } private void onDeviceDisappeared(String address) { boolean hasDeviceListeners = false; Loading Loading @@ -1177,6 +1248,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private void initBleScanning() { Log.i(LOG_TAG, "initBleScanning()"); boolean bluetoothReady = mBluetoothAdapter.registerServiceLifecycleCallback( new BluetoothAdapter.ServiceLifecycleCallback() { @Override Loading @@ -1196,15 +1269,22 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } void startBleScan() { Log.i(LOG_TAG, "startBleScan()"); List<ScanFilter> filters = getBleScanFilters(); if (filters.isEmpty()) { return; } mBluetoothAdapter.getBluetoothLeScanner().startScan( BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner(); if (scanner == null) { Log.w(LOG_TAG, "scanner == null (likely BLE isn't ON yet)"); } else { scanner.startScan( filters, new ScanSettings.Builder().setScanMode(SCAN_MODE_BALANCED).build(), mBleScanCallback); } } void restartBleScan() { mBluetoothAdapter.getBluetoothLeScanner().stopScan(mBleScanCallback); Loading Loading
core/java/com/android/internal/infra/ServiceConnector.java +39 −0 Original line number Diff line number Diff line Loading @@ -726,4 +726,43 @@ public interface ServiceConnector<I extends IInterface> { } } } /** * A {@link ServiceConnector} that doesn't connect to anything. * * @param <T> the type of the {@link IInterface ipc interface} for the remote service */ class NoOp<T extends IInterface> extends AndroidFuture<Object> implements ServiceConnector<T> { { completeExceptionally(new IllegalStateException("ServiceConnector is a no-op")); } @Override public boolean run(@NonNull VoidJob<T> job) { return false; } @Override public AndroidFuture<Void> post(@NonNull VoidJob<T> job) { return (AndroidFuture) this; } @Override public <R> AndroidFuture<R> postForResult(@NonNull Job<T, R> job) { return (AndroidFuture) this; } @Override public <R> AndroidFuture<R> postAsync(@NonNull Job<T, CompletableFuture<R>> job) { return (AndroidFuture) this; } @Override public AndroidFuture<T> connect() { return (AndroidFuture) this; } @Override public void unbind() {} } }
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +105 −25 Original line number Diff line number Diff line Loading @@ -20,8 +20,11 @@ package com.android.server.companion; import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES; import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED; import static android.content.Context.BIND_IMPORTANT; import static android.content.pm.PackageManager.MATCH_ALL; import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.CollectionUtils.emptyIfNull; import static com.android.internal.util.CollectionUtils.filter; import static com.android.internal.util.CollectionUtils.find; import static com.android.internal.util.CollectionUtils.forEach; import static com.android.internal.util.CollectionUtils.map; Loading @@ -45,6 +48,7 @@ import android.app.PendingIntent; import android.app.role.RoleManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; Loading @@ -58,15 +62,18 @@ import android.companion.ICompanionDeviceDiscoveryService; import android.companion.ICompanionDeviceManager; import android.companion.ICompanionDeviceService; import android.companion.IFindDeviceCallback; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.NetworkPolicyManager; import android.os.Binder; Loading Loading @@ -189,6 +196,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener = new BluetoothDeviceConnectedListener(); private BleStateBroadcastReceiver mBleStateBroadcastReceiver = new BleStateBroadcastReceiver(); private List<String> mCurrentlyConnectedDevices = new ArrayList<>(); private ArrayMap<String, Date> mDevicesLastNearby = new ArrayMap<>(); private UnbindDeviceListenersRunnable Loading Loading @@ -286,11 +294,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public void onBootPhase(int phase) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { // Init Bluetooth mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter != null) { mBluetoothAdapter.registerBluetoothConnectionCallback( getContext().getMainExecutor(), mBluetoothDeviceConnectedListener); getContext().registerReceiver( mBleStateBroadcastReceiver, mBleStateBroadcastReceiver.mIntentFilter); initBleScanning(); } else { Log.w(LOG_TAG, "No BluetoothAdapter available"); Loading Loading @@ -553,7 +564,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return true; } return CollectionUtils.any( return any( getAllAssociations(userId, packageName), a -> Objects.equals(a.getDeviceMacAddress(), macAddress)); } Loading Loading @@ -604,6 +615,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return association; } })); restartBleScan(); } private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { Loading Loading @@ -917,7 +930,12 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private List<UserInfo> getAllUsers() { return getContext().getSystemService(UserManager.class).getUsers(); long identity = Binder.clearCallingIdentity(); try { return mUserManager.getUsers(); } finally { Binder.restoreCallingIdentity(identity); } } private Set<Association> getAllAssociations(int userId, @Nullable String packageFilter) { Loading @@ -927,11 +945,16 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private Set<Association> getAllAssociations() { long identity = Binder.clearCallingIdentity(); try { ArraySet<Association> result = new ArraySet<>(); for (UserInfo user : mUserManager.getAliveUsers()) { result.addAll(getAllAssociations(user.id)); } return result; } finally { Binder.restoreCallingIdentity(identity); } } Loading Loading @@ -1029,11 +1052,28 @@ public class CompanionDeviceManagerService extends SystemService implements Bind Association a) { return mDeviceListenerServiceConnectors.forUser(a.getUserId()).computeIfAbsent( a.getPackageName(), pkg -> new ServiceConnector.Impl<>(getContext(), new Intent(CompanionDeviceService.SERVICE_INTERFACE), pkg -> createDeviceListenerServiceConnector(a)); } private ServiceConnector<ICompanionDeviceService> createDeviceListenerServiceConnector( Association a) { List<ResolveInfo> resolveInfos = getContext().getPackageManager().queryIntentServicesAsUser( new Intent(CompanionDeviceService.SERVICE_INTERFACE), MATCH_ALL, a.getUserId()); List<ResolveInfo> packageResolveInfos = filter(resolveInfos, info -> Objects.equals(info.serviceInfo.packageName, a.getPackageName())); if (packageResolveInfos.size() != 1) { Log.w(LOG_TAG, "Device presence listener package must have exactly one " + "CompanionDeviceService, but " + a.getPackageName() + " has " + packageResolveInfos.size()); return new ServiceConnector.NoOp<>(); } ComponentName componentName = packageResolveInfos.get(0).serviceInfo.getComponentName(); Log.i(LOG_TAG, "Initializing CompanionDeviceService binding for " + componentName); return new ServiceConnector.Impl<>(getContext(), new Intent(CompanionDeviceService.SERVICE_INTERFACE).setComponent(componentName), BIND_IMPORTANT, a.getUserId(), ICompanionDeviceService.Stub::asInterface)); ICompanionDeviceService.Stub::asInterface); } private class BleScanCallback extends ScanCallback { Loading @@ -1059,8 +1099,34 @@ public class CompanionDeviceManagerService extends SystemService implements Bind if (errorCode == SCAN_FAILED_ALREADY_STARTED) { // ignore - this might happen if BT tries to auto-restore scans for us in the // future Log.i(LOG_TAG, "Ignoring BLE scan error: SCAN_FAILED_ALREADY_STARTED"); } else { Log.wtf(LOG_TAG, "Failed to start BLE scan: error " + errorCode); Log.w(LOG_TAG, "Failed to start BLE scan: error " + errorCode); } } } private class BleStateBroadcastReceiver extends BroadcastReceiver { final IntentFilter mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); @Override public void onReceive(Context context, Intent intent) { int previousState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, -1); int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); Log.i(LOG_TAG, "Received BT state transition broadcast: " + BluetoothAdapter.nameForState(previousState) + " -> " + BluetoothAdapter.nameForState(newState)); boolean bleOn = newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_BLE_ON; if (bleOn) { if (mBluetoothAdapter.getBluetoothLeScanner() != null) { startBleScan(); } else { Log.wtf(LOG_TAG, "BLE on, but BluetoothLeScanner == null"); } } } } Loading Loading @@ -1125,7 +1191,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private void onDeviceNearby(String address) { Date timestamp = new Date(); mDevicesLastNearby.put(address, timestamp); Date oldTimestamp = mDevicesLastNearby.put(address, timestamp); cancelUnbindDeviceListener(address); Loading @@ -1133,6 +1199,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind .computeIfAbsent(address, addr -> new TriggerDeviceDisappearedRunnable(address)) .schedule(); // Avoid spamming the app if device is already known to be nearby boolean justAppeared = oldTimestamp == null || timestamp.getTime() - oldTimestamp.getTime() >= DEVICE_DISAPPEARED_TIMEOUT_MS; if (justAppeared) { for (Association association : getAllAssociations(address)) { if (association.isNotifyOnDeviceNearby()) { if (DEBUG) { Loading @@ -1145,6 +1215,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } } } private void onDeviceDisappeared(String address) { boolean hasDeviceListeners = false; Loading Loading @@ -1177,6 +1248,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private void initBleScanning() { Log.i(LOG_TAG, "initBleScanning()"); boolean bluetoothReady = mBluetoothAdapter.registerServiceLifecycleCallback( new BluetoothAdapter.ServiceLifecycleCallback() { @Override Loading @@ -1196,15 +1269,22 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } void startBleScan() { Log.i(LOG_TAG, "startBleScan()"); List<ScanFilter> filters = getBleScanFilters(); if (filters.isEmpty()) { return; } mBluetoothAdapter.getBluetoothLeScanner().startScan( BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner(); if (scanner == null) { Log.w(LOG_TAG, "scanner == null (likely BLE isn't ON yet)"); } else { scanner.startScan( filters, new ScanSettings.Builder().setScanMode(SCAN_MODE_BALANCED).build(), mBleScanCallback); } } void restartBleScan() { mBluetoothAdapter.getBluetoothLeScanner().stopScan(mBleScanCallback); Loading