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

Commit 92f39572 authored by Ze Li's avatar Ze Li Committed by Android (Google) Code Review
Browse files

Merge "[Hide DCK devices] Implementation to determine check is a Bluetooth...

Merge "[Hide DCK devices] Implementation to determine check is a Bluetooth device is exclusively managed." into main
parents 0d913a04 250f0904
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -24,6 +25,7 @@ import android.util.Pair;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.core.graphics.drawable.IconCompat;

@@ -31,9 +33,12 @@ import com.android.settingslib.R;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.settingslib.widget.AdaptiveOutlineDrawable;

import com.google.common.collect.ImmutableSet;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -47,6 +52,8 @@ public class BluetoothUtils {
    public static final String BT_ADVANCED_HEADER_ENABLED = "bt_advanced_header_enabled";
    private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
    private static final String KEY_HEARABLE_CONTROL_SLICE = "HEARABLE_CONTROL_SLICE_WITH_WIDTH";
    private static final Set<String> EXCLUSIVE_MANAGERS = ImmutableSet.of(
            "com.google.android.gms.dck");

    private static ErrorListener sErrorListener;

@@ -647,4 +654,66 @@ public class BluetoothUtils {
    private static String generateExpressionWithTag(String tag, String value) {
        return getTagStart(tag) + value + getTagEnd(tag);
    }

    /**
     * Returns the BluetoothDevice's exclusive manager
     * ({@link BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata) if it exists and is in the
     * given set, otherwise null.
     */
    @Nullable
    private static String getAllowedExclusiveManager(BluetoothDevice bluetoothDevice) {
        byte[] exclusiveManagerNameBytes = bluetoothDevice.getMetadata(
                BluetoothDevice.METADATA_EXCLUSIVE_MANAGER);
        if (exclusiveManagerNameBytes == null) {
            Log.d(TAG, "Bluetooth device " + bluetoothDevice.getName()
                    + " doesn't have exclusive manager");
            return null;
        }
        String exclusiveManagerName = new String(exclusiveManagerNameBytes);
        return getExclusiveManagers().contains(exclusiveManagerName) ? exclusiveManagerName
                : null;
    }

    /**
     * Checks if given package is installed
     */
    private static boolean isPackageInstalled(Context context,
            String packageName) {
        PackageManager packageManager = context.getPackageManager();
        try {
            packageManager.getPackageInfo(packageName, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            Log.d(TAG, "Package " + packageName + " is not installed");
        }
        return false;
    }

    /**
     * A BluetoothDevice is exclusively managed if
     * 1) it has field {@link BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata.
     * 2) the exclusive manager app name is in the allowlist.
     * 3) the exclusive manager app is installed.
     */
    public static boolean isExclusivelyManagedBluetoothDevice(@NonNull Context context,
            @NonNull BluetoothDevice bluetoothDevice) {
        String exclusiveManagerName = getAllowedExclusiveManager(bluetoothDevice);
        if (exclusiveManagerName == null) {
            return false;
        }
        if (!isPackageInstalled(context, exclusiveManagerName)) {
            return false;
        } else {
            Log.d(TAG, "Found exclusively managed app " + exclusiveManagerName);
            return true;
        }
    }

    /**
     * Return the allowlist for exclusive manager names.
     */
    @NonNull
    public static Set<String> getExclusiveManagers() {
        return EXCLUSIVE_MANAGERS;
    }
}
+58 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ package com.android.settingslib.bluetooth;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -24,6 +26,8 @@ import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.Uri;
@@ -49,6 +53,8 @@ public class BluetoothUtilsTest {
    private BluetoothDevice mBluetoothDevice;
    @Mock
    private AudioManager mAudioManager;
    @Mock
    private PackageManager mPackageManager;

    private Context mContext;
    private static final String STRING_METADATA = "string_metadata";
@@ -59,6 +65,7 @@ public class BluetoothUtilsTest {
    private static final String CONTROL_METADATA =
            "<HEARABLE_CONTROL_SLICE_WITH_WIDTH>" + STRING_METADATA
                    + "</HEARABLE_CONTROL_SLICE_WITH_WIDTH>";
    private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";

    @Before
    public void setUp() {
@@ -372,4 +379,55 @@ public class BluetoothUtilsTest {
        assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice,
                mAudioManager)).isEqualTo(false);
    }

    @Test
    public void isExclusivelyManagedBluetoothDevice_isNotExclusivelyManaged_returnFalse() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                null);

        assertThat(BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
                mBluetoothDevice)).isEqualTo(false);
    }

    @Test
    public void isExclusivelyManagedBluetoothDevice_isNotInAllowList_returnFalse() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());

        assertThat(BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
                mBluetoothDevice)).isEqualTo(false);
    }

    @Test
    public void isExclusivelyManagedBluetoothDevice_packageNotInstalled_returnFalse()
            throws Exception {
        final String exclusiveManagerName =
                BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
                        FAKE_EXCLUSIVE_MANAGER_NAME);

        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                exclusiveManagerName.getBytes());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
                exclusiveManagerName, 0);

        assertThat(BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
                mBluetoothDevice)).isEqualTo(false);
    }

    @Test
    public void isExclusivelyManagedBluetoothDevice_isExclusivelyManaged_returnTrue()
            throws Exception {
        final String exclusiveManagerName =
                BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
                        FAKE_EXCLUSIVE_MANAGER_NAME);

        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                exclusiveManagerName.getBytes());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);

        assertThat(BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
                mBluetoothDevice)).isEqualTo(true);
    }
}