Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56f4c536 authored by Guojing Yuan's avatar Guojing Yuan Committed by Android (Google) Code Review
Browse files

Merge "[CDM][Refactoring 6/N] Some device presence refactoring" into main

parents f1666967 6c735f22
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -103,10 +103,10 @@ import com.android.server.companion.datatransfer.SystemDataTransferRequestStore;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceCall;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncControllerCallback;
import com.android.server.companion.presence.CompanionAppBinder;
import com.android.server.companion.presence.DevicePresenceProcessor;
import com.android.server.companion.presence.ObservableUuid;
import com.android.server.companion.presence.ObservableUuidStore;
import com.android.server.companion.devicepresence.CompanionAppBinder;
import com.android.server.companion.devicepresence.DevicePresenceProcessor;
import com.android.server.companion.devicepresence.ObservableUuid;
import com.android.server.companion.devicepresence.ObservableUuidStore;
import com.android.server.companion.transport.CompanionTransportManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
+2 −2
Original line number Diff line number Diff line
@@ -36,8 +36,8 @@ import com.android.server.companion.association.DisassociationProcessor;
import com.android.server.companion.datatransfer.SystemDataTransferProcessor;
import com.android.server.companion.datatransfer.contextsync.BitmapUtils;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController;
import com.android.server.companion.presence.DevicePresenceProcessor;
import com.android.server.companion.presence.ObservableUuid;
import com.android.server.companion.devicepresence.DevicePresenceProcessor;
import com.android.server.companion.devicepresence.ObservableUuid;
import com.android.server.companion.transport.CompanionTransportManager;

import java.io.PrintWriter;
+2 −2
Original line number Diff line number Diff line
@@ -37,8 +37,8 @@ import android.os.UserHandle;
import android.util.Slog;

import com.android.server.companion.datatransfer.SystemDataTransferRequestStore;
import com.android.server.companion.presence.CompanionAppBinder;
import com.android.server.companion.presence.DevicePresenceProcessor;
import com.android.server.companion.devicepresence.CompanionAppBinder;
import com.android.server.companion.devicepresence.DevicePresenceProcessor;
import com.android.server.companion.transport.CompanionTransportManager;

/**
+22 −122
Original line number Diff line number Diff line
@@ -15,27 +15,15 @@
 */


package com.android.server.companion.presence;
package com.android.server.companion.devicepresence;

import static android.bluetooth.BluetoothAdapter.ACTION_BLE_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_PREVIOUS_STATE;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.nameForState;
import static android.bluetooth.le.ScanCallback.SCAN_FAILED_ALREADY_STARTED;
import static android.bluetooth.le.ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED;
import static android.bluetooth.le.ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED;
import static android.bluetooth.le.ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
import static android.bluetooth.le.ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES;
import static android.bluetooth.le.ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY;
import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES;
import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_FIRST_MATCH;
import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_MATCH_LOST;
import static android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_POWER;

import static com.android.server.companion.presence.DevicePresenceProcessor.DEBUG;
import static com.android.server.companion.utils.Utils.btDeviceToString;

import static java.util.Objects.requireNonNull;

import android.annotation.MainThread;
@@ -56,21 +44,19 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Slog;

import com.android.server.companion.association.AssociationStore;
import com.android.server.companion.association.AssociationStore.ChangeType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@SuppressLint("LongLogTag")
class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
    private static final String TAG = "CDM_BleCompanionDeviceScanner";
class BleDeviceProcessor implements AssociationStore.OnChangeListener {
    private static final String TAG = "CDM_BleDeviceProcessor";

    interface Callback {
        void onBleCompanionDeviceFound(int associationId, int userId);
@@ -78,26 +64,27 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
        void onBleCompanionDeviceLost(int associationId, int userId);
    }

    private final @NonNull AssociationStore mAssociationStore;
    private final @NonNull Callback mCallback;
    @NonNull
    private final AssociationStore mAssociationStore;
    @NonNull
    private final Callback mCallback;

    // Non-null after init().
    private @Nullable BluetoothAdapter mBtAdapter;
    @Nullable
    private BluetoothAdapter mBtAdapter;
    // Non-null after init() and when BLE is available. Otherwise - null.
    private @Nullable BluetoothLeScanner mBleScanner;
    @Nullable
    private BluetoothLeScanner mBleScanner;
    // Only accessed from the Main thread.
    private boolean mScanning = false;

    BleCompanionDeviceScanner(
            @NonNull AssociationStore associationStore, @NonNull Callback callback) {
    BleDeviceProcessor(@NonNull AssociationStore associationStore, @NonNull Callback callback) {
        mAssociationStore = associationStore;
        mCallback = callback;
    }

    @MainThread
    void init(@NonNull Context context, @NonNull BluetoothAdapter btAdapter) {
        if (DEBUG) Log.i(TAG, "init()");

        if (mBtAdapter != null) {
            throw new IllegalStateException(getClass().getSimpleName() + " is already initialized");
        }
@@ -113,9 +100,7 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
    final void restartScan() {
        enforceInitialized();

        if (DEBUG) Log.i(TAG , "restartScan()");
        if (mBleScanner == null) {
            if (DEBUG) Log.d(TAG, "  > BLE is not available");
            return;
        }

@@ -138,12 +123,8 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
        enforceInitialized();

        final boolean bleAvailable = mBtAdapter.isLeEnabled();
        if (DEBUG) {
            Log.i(TAG, "checkBleState() bleAvailable=" + bleAvailable);
        }
        if ((bleAvailable && mBleScanner != null) || (!bleAvailable && mBleScanner == null)) {
            // Nothing changed.
            if (DEBUG) Log.i(TAG, "  > BLE status did not change");
            return;
        }

@@ -153,12 +134,9 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
                // Oops, that's a race condition. Can return.
                return;
            }
            if (DEBUG) Log.i(TAG, "  > BLE is now available");

            startScan();
        } else {
            if (DEBUG) Log.i(TAG, "  > BLE is now unavailable");

            stopScanIfNeeded();
            mBleScanner = null;
        }
@@ -194,13 +172,7 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
            }
        }
        if (macAddresses.isEmpty()) {
            if (DEBUG) Log.i(TAG, "  > there are no (associated) devices to Scan for.");
            return;
        } else {
            if (DEBUG) {
                Log.d(TAG, "  > addresses=(n=" + macAddresses.size() + ")"
                        + "[" + String.join(", ", macAddresses) + "]");
            }
        }

        final List<ScanFilter> filters = new ArrayList<>(macAddresses.size());
@@ -230,7 +202,6 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {

        Slog.i(TAG, "stopBleScan()");
        if (!mScanning) {
            if (DEBUG) Log.d(TAG, "  > not scanning.");
            return;
        }
        // mScanCallback is non-null here - it cannot be null when mScanning is true.
@@ -252,26 +223,16 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {

    @MainThread
    private void notifyDeviceFound(@NonNull BluetoothDevice device) {
        if (DEBUG) Log.i(TAG, "notifyDevice_Found()" + btDeviceToString(device));

        final List<AssociationInfo> associations =
                mAssociationStore.getActiveAssociationsByAddress(device.getAddress());
        if (DEBUG) Log.d(TAG, "  > associations=" + Arrays.toString(associations.toArray()));

        for (AssociationInfo association : associations) {
        for (AssociationInfo association : mAssociationStore.getActiveAssociationsByAddress(
                device.getAddress())) {
            mCallback.onBleCompanionDeviceFound(association.getId(), association.getUserId());
        }
    }

    @MainThread
    private void notifyDeviceLost(@NonNull BluetoothDevice device) {
        if (DEBUG) Log.i(TAG, "notifyDevice_Lost()" + btDeviceToString(device));

        final List<AssociationInfo> associations =
                mAssociationStore.getActiveAssociationsByAddress(device.getAddress());
        if (DEBUG) Log.d(TAG, "  > associations=" + Arrays.toString(associations.toArray()));

        for (AssociationInfo association : associations) {
        for (AssociationInfo association : mAssociationStore.getActiveAssociationsByAddress(
                device.getAddress())) {
            mCallback.onBleCompanionDeviceLost(association.getId(), association.getUserId());
        }
    }
@@ -280,17 +241,6 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
        final BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final int prevState = intent.getIntExtra(EXTRA_PREVIOUS_STATE, -1);
                final int state = intent.getIntExtra(EXTRA_STATE, -1);

                if (DEBUG) {
                    // The action is either STATE_CHANGED or BLE_STATE_CHANGED.
                    final String action =
                            intent.getAction().replace("android.bluetooth.adapter.", "bt.");
                    Log.d(TAG, "on(Broadcast)Receive() " + action + ": "
                            + nameForBtState(prevState) + "->" + nameForBtState(state));
                }

                checkBleState();
            }
        };
@@ -313,16 +263,6 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
        public void onScanResult(int callbackType, ScanResult result) {
            final BluetoothDevice device = result.getDevice();

            if (DEBUG) {
                Log.d(TAG, "onScanResult() " + nameForBleScanCallbackType(callbackType)
                        + " device=" + btDeviceToString(device));
                Log.v(TAG, "  > scanResult=" + result);

                final List<AssociationInfo> associations =
                        mAssociationStore.getActiveAssociationsByAddress(device.getAddress());
                Log.v(TAG, "  > associations=" + Arrays.toString(associations.toArray()));
            }

            switch (callbackType) {
                case CALLBACK_TYPE_FIRST_MATCH:
                    notifyDeviceFound(device);
@@ -342,60 +282,20 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
        @MainThread
        @Override
        public void onScanFailed(int errorCode) {
            if (DEBUG) Log.w(TAG, "onScanFailed() " + nameForBleScanErrorCode(errorCode));
            mScanning = false;
        }
    };

    private static String nameForBtState(int state) {
        return nameForState(state) + "(" + state + ")";
    }

    private static String nameForBleScanCallbackType(int callbackType) {
        final String name;
        switch (callbackType) {
            case CALLBACK_TYPE_ALL_MATCHES:
                name = "ALL_MATCHES";
                break;
            case CALLBACK_TYPE_FIRST_MATCH:
                name = "FIRST_MATCH";
                break;
            case CALLBACK_TYPE_MATCH_LOST:
                name = "MATCH_LOST";
                break;
            default:
                name = "Unknown";
        }
        final String name = switch (callbackType) {
            case CALLBACK_TYPE_ALL_MATCHES -> "ALL_MATCHES";
            case CALLBACK_TYPE_FIRST_MATCH -> "FIRST_MATCH";
            case CALLBACK_TYPE_MATCH_LOST -> "MATCH_LOST";
            default -> "Unknown";
        };
        return name + "(" + callbackType + ")";
    }

    private static String nameForBleScanErrorCode(int errorCode) {
        final String name;
        switch (errorCode) {
            case SCAN_FAILED_ALREADY_STARTED:
                name = "ALREADY_STARTED";
                break;
            case SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
                name = "APPLICATION_REGISTRATION_FAILED";
                break;
            case SCAN_FAILED_INTERNAL_ERROR:
                name = "INTERNAL_ERROR";
                break;
            case SCAN_FAILED_FEATURE_UNSUPPORTED:
                name = "FEATURE_UNSUPPORTED";
                break;
            case SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES:
                name = "OUT_OF_HARDWARE_RESOURCES";
                break;
            case SCAN_FAILED_SCANNING_TOO_FREQUENTLY:
                name = "SCANNING_TOO_FREQUENTLY";
                break;
            default:
                name = "Unknown";
        }
        return name + "(" + errorCode + ")";
    }

    private static final ScanSettings SCAN_SETTINGS = new ScanSettings.Builder()
            .setCallbackType(CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST)
            .setScanMode(SCAN_MODE_LOW_POWER)
+21 −73
Original line number Diff line number Diff line
@@ -14,14 +14,11 @@
 * limitations under the License.
 */

package com.android.server.companion.presence;
package com.android.server.companion.devicepresence;

import static android.companion.DevicePresenceEvent.EVENT_BT_CONNECTED;
import static android.companion.DevicePresenceEvent.EVENT_BT_DISCONNECTED;

import static com.android.server.companion.presence.DevicePresenceProcessor.DEBUG;
import static com.android.server.companion.utils.Utils.btDeviceToString;

import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
@@ -32,8 +29,6 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.ParcelUuid;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import com.android.internal.util.ArrayUtils;
import com.android.server.companion.association.AssociationStore;
@@ -45,10 +40,10 @@ import java.util.List;
import java.util.Map;

@SuppressLint("LongLogTag")
public class BluetoothCompanionDeviceConnectionListener
public class BluetoothDeviceProcessor
        extends BluetoothAdapter.BluetoothConnectionCallback
        implements AssociationStore.OnChangeListener {
    private static final String TAG = "CDM_BluetoothCompanionDeviceConnectionListener";
    private static final String TAG = "CDM_BluetoothDeviceProcessor";

    interface Callback {
        void onBluetoothCompanionDeviceConnected(int associationId, int userId);
@@ -58,24 +53,25 @@ public class BluetoothCompanionDeviceConnectionListener
        void onDevicePresenceEventByUuid(ObservableUuid uuid, int event);
    }

    private final @NonNull AssociationStore mAssociationStore;
    private final @NonNull Callback mCallback;
    /** A set of ALL connected BT device (not only companion.) */
    private final @NonNull Map<MacAddress, BluetoothDevice> mAllConnectedDevices = new HashMap<>();
    @NonNull
    private final AssociationStore mAssociationStore;
    @NonNull
    private final ObservableUuidStore mObservableUuidStore;
    @NonNull
    private final Callback mCallback;

    private final @NonNull ObservableUuidStore mObservableUuidStore;
    /** A set of ALL connected BT device (not only companion.) */
    @NonNull
    private final Map<MacAddress, BluetoothDevice> mAllConnectedDevices = new HashMap<>();

    BluetoothCompanionDeviceConnectionListener(UserManager userManager,
            @NonNull AssociationStore associationStore,
    BluetoothDeviceProcessor(@NonNull AssociationStore associationStore,
            @NonNull ObservableUuidStore observableUuidStore, @NonNull Callback callback) {
        mAssociationStore = associationStore;
        mObservableUuidStore = observableUuidStore;
        mCallback = callback;
    }

    public void init(@NonNull BluetoothAdapter btAdapter) {
        if (DEBUG) Log.i(TAG, "init()");

    void init(@NonNull BluetoothAdapter btAdapter) {
        btAdapter.registerBluetoothConnectionCallback(
                new HandlerExecutor(Handler.getMain()), /* callback */this);
        mAssociationStore.registerLocalListener(this);
@@ -87,13 +83,9 @@ public class BluetoothCompanionDeviceConnectionListener
     */
    @Override
    public void onDeviceConnected(@NonNull BluetoothDevice device) {
        if (DEBUG) Log.i(TAG, "onDevice_Connected() " + btDeviceToString(device));

        final MacAddress macAddress = MacAddress.fromString(device.getAddress());
        final int userId = UserHandle.myUserId();

        if (mAllConnectedDevices.put(macAddress, device) != null) {
            if (DEBUG) Log.w(TAG, "Device " + btDeviceToString(device) + " is already connected.");
            return;
        }

@@ -108,18 +100,9 @@ public class BluetoothCompanionDeviceConnectionListener
    @Override
    public void onDeviceDisconnected(@NonNull BluetoothDevice device,
            int reason) {
        if (DEBUG) {
            Log.i(TAG, "onDevice_Disconnected() " + btDeviceToString(device));
            Log.d(TAG, "  reason=" + disconnectReasonToString(reason));
        }

        final MacAddress macAddress = MacAddress.fromString(device.getAddress());
        final int userId = UserHandle.myUserId();

        if (mAllConnectedDevices.remove(macAddress) == null) {
            if (DEBUG) {
                Log.w(TAG, "The device wasn't tracked as connected " + btDeviceToString(device));
            }
            return;
        }

@@ -130,22 +113,6 @@ public class BluetoothCompanionDeviceConnectionListener
        int userId = UserHandle.myUserId();
        final List<AssociationInfo> associations =
                mAssociationStore.getActiveAssociationsByAddress(device.getAddress());
        final List<ObservableUuid> observableUuids =
                mObservableUuidStore.getObservableUuidsForUser(userId);
        final ParcelUuid[] bluetoothDeviceUuids = device.getUuids();

        final List<ParcelUuid> deviceUuids = ArrayUtils.isEmpty(bluetoothDeviceUuids)
                ? Collections.emptyList() : Arrays.asList(bluetoothDeviceUuids);

        if (DEBUG) {
            Log.d(TAG, "onDevice_ConnectivityChanged() " + btDeviceToString(device)
                    + " connected=" + connected);
            if (associations.isEmpty()) {
                Log.d(TAG, "  > No CDM associations");
            } else {
                Log.d(TAG, "  > associations=" + Arrays.toString(associations.toArray()));
            }
        }

        for (AssociationInfo association : associations) {
            if (!association.isNotifyOnDeviceNearby()) continue;
@@ -157,6 +124,12 @@ public class BluetoothCompanionDeviceConnectionListener
            }
        }

        final List<ObservableUuid> observableUuids =
                mObservableUuidStore.getObservableUuidsForUser(userId);
        final ParcelUuid[] bluetoothDeviceUuids = device.getUuids();
        final List<ParcelUuid> deviceUuids = ArrayUtils.isEmpty(bluetoothDeviceUuids)
                ? Collections.emptyList() : Arrays.asList(bluetoothDeviceUuids);

        for (ObservableUuid uuid : observableUuids) {
            if (deviceUuids.contains(uuid.getUuid())) {
                mCallback.onDevicePresenceEventByUuid(uuid, connected ? EVENT_BT_CONNECTED
@@ -167,34 +140,9 @@ public class BluetoothCompanionDeviceConnectionListener

    @Override
    public void onAssociationAdded(AssociationInfo association) {
        if (DEBUG) Log.d(TAG, "onAssociation_Added() " + association);

        if (mAllConnectedDevices.containsKey(association.getDeviceMacAddress())) {
            mCallback.onBluetoothCompanionDeviceConnected(
                    association.getId(), association.getUserId());
        }
    }

    @Override
    public void onAssociationRemoved(AssociationInfo association) {
        // Intentionally do nothing: CompanionDevicePresenceMonitor will do all the bookkeeping
        // required.
    }

    @Override
    public void onAssociationUpdated(AssociationInfo association, boolean addressChanged) {
        if (DEBUG) {
            Log.d(TAG, "onAssociation_Updated() addrChange=" + addressChanged
                    + " " + association);
        }

        if (!addressChanged) {
            // Don't need to do anything.
            return;
        }

        // At the moment CDM does allow changing association addresses, so we will never come here.
        // This will be implemented when CDM support updating addresses.
        throw new IllegalArgumentException("Address changes are not supported.");
    }
}
Loading