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

Commit 2a1cac87 authored by Srinivas Patibandla's avatar Srinivas Patibandla Committed by Android (Google) Code Review
Browse files

Merge "[Hide DCK Device] Update the exclusive manager verification" into main

parents d05be354 79eea770
Loading
Loading
Loading
Loading
+23 −28
Original line number Diff line number Diff line
@@ -10,8 +10,10 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -37,12 +39,9 @@ import com.android.settingslib.flags.Flags;
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;

@@ -56,8 +55,6 @@ 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;

@@ -740,14 +737,13 @@ public class BluetoothUtils {

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

    /** Checks if given package is installed */
    private static boolean isPackageInstalled(Context context, String packageName) {
    /** Checks if given package is installed and enabled */
    private static boolean isPackageInstalledAndEnabled(Context context, String packageName) {
        PackageManager packageManager = context.getPackageManager();
        try {
            packageManager.getPackageInfo(packageName, 0);
            return true;
            ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
            return appInfo.enabled;
        } catch (PackageManager.NameNotFoundException e) {
            Log.d(TAG, "Package " + packageName + " is not installed");
            Log.d(TAG, "Package " + packageName + " is not installed/enabled");
        }
        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.
     * BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata. 2) the exclusive manager app is
     * installed and enabled.
     */
    public static boolean isExclusivelyManagedBluetoothDevice(
            @NonNull Context context, @NonNull BluetoothDevice bluetoothDevice) {
        String exclusiveManagerName = getAllowedExclusiveManager(bluetoothDevice);
        String exclusiveManagerName = getExclusiveManager(bluetoothDevice);
        if (exclusiveManagerName == null) {
            return false;
        }
        if (!isPackageInstalled(context, exclusiveManagerName)) {

        ComponentName exclusiveManagerComponent =
                ComponentName.unflattenFromString(exclusiveManagerName);
        String exclusiveManagerPackage = exclusiveManagerComponent != null
                ? exclusiveManagerComponent.getPackageName() : exclusiveManagerName;

        if (!isPackageInstalledAndEnabled(context, exclusiveManagerPackage)) {
            return false;
        } else {
            Log.d(TAG, "Found exclusively managed app " + exclusiveManagerName);
            Log.d(TAG, "Found exclusively managed app " + exclusiveManagerPackage);
            return true;
        }
    }

    /** Return the allowlist for exclusive manager names. */
    @NonNull
    public static Set<String> getExclusiveManagers() {
        return EXCLUSIVE_MANAGERS;
    }

    /**
     * Get CSIP group id for {@link CachedBluetoothDevice}.
     *
+61 −20
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
@@ -80,7 +80,8 @@ 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";
    private static final String TEST_EXCLUSIVE_MANAGER_PACKAGE = "com.test.manager";
    private static final String TEST_EXCLUSIVE_MANAGER_COMPONENT = "com.test.manager/.component";

    @Before
    public void setUp() {
@@ -399,7 +400,7 @@ public class BluetoothUtilsTest {
    }

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

@@ -408,42 +409,82 @@ public class BluetoothUtilsTest {
    }

    @Test
    public void isExclusivelyManagedBluetoothDevice_isNotInAllowList_returnFalse() {
    public void isExclusivelyManaged_hasPackageName_packageNotInstalled_returnFalse()
            throws Exception {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
                TEST_EXCLUSIVE_MANAGER_PACKAGE.getBytes());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
                .getApplicationInfo(TEST_EXCLUSIVE_MANAGER_PACKAGE, 0);

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

    @Test
    public void isExclusivelyManagedBluetoothDevice_packageNotInstalled_returnFalse()
    public void isExclusivelyManaged_hasComponentName_packageNotInstalled_returnFalse()
            throws Exception {
        final String exclusiveManagerName =
                BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
                        FAKE_EXCLUSIVE_MANAGER_NAME);
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                TEST_EXCLUSIVE_MANAGER_COMPONENT.getBytes());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
                .getApplicationInfo(TEST_EXCLUSIVE_MANAGER_PACKAGE, 0);

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

    @Test
    public void isExclusivelyManaged_hasPackageName_packageNotEnabled_returnFalse()
             throws Exception {
        ApplicationInfo appInfo = new ApplicationInfo();
        appInfo.enabled = false;
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doReturn(appInfo).when(mPackageManager).getApplicationInfo(
                TEST_EXCLUSIVE_MANAGER_PACKAGE, 0);
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                exclusiveManagerName.getBytes());
                TEST_EXCLUSIVE_MANAGER_PACKAGE.getBytes());

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

    @Test
    public void isExclusivelyManaged_hasComponentName_packageNotEnabled_returnFalse()
            throws Exception {
        ApplicationInfo appInfo = new ApplicationInfo();
        appInfo.enabled = false;
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
                exclusiveManagerName, 0);
        doReturn(appInfo).when(mPackageManager).getApplicationInfo(
                TEST_EXCLUSIVE_MANAGER_PACKAGE, 0);
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                TEST_EXCLUSIVE_MANAGER_COMPONENT.getBytes());

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

    @Test
    public void isExclusivelyManagedBluetoothDevice_isExclusivelyManaged_returnTrue()
    public void isExclusivelyManaged_hasPackageName_packageInstalledAndEnabled_returnTrue()
            throws Exception {
        final String exclusiveManagerName =
                BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
                        FAKE_EXCLUSIVE_MANAGER_NAME);
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                TEST_EXCLUSIVE_MANAGER_PACKAGE.getBytes());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
                TEST_EXCLUSIVE_MANAGER_PACKAGE, 0);

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

    @Test
    public void isExclusivelyManaged_hasComponentName_packageInstalledAndEnabled_returnTrue()
            throws Exception {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
                exclusiveManagerName.getBytes());
                TEST_EXCLUSIVE_MANAGER_COMPONENT.getBytes());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
        doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
                TEST_EXCLUSIVE_MANAGER_PACKAGE, 0);

        assertThat(BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
            mBluetoothDevice)).isEqualTo(true);
+22 −29
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
package com.android.systemui.bluetooth.qsdialog

import android.bluetooth.BluetoothDevice
import android.content.pm.PackageInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.media.AudioManager
import android.platform.test.annotations.DisableFlags
@@ -25,7 +25,6 @@ import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.flags.Flags
import com.android.systemui.SysuiTestCase
@@ -120,11 +119,10 @@ class DeviceItemFactoryTest : SysuiTestCase() {
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
    fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
        val exclusiveManagerName =
            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
            .thenReturn(exclusiveManagerName.toByteArray())
        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo())
            .thenReturn(TEST_EXCLUSIVE_MANAGER.toByteArray())
        `when`(packageManager.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0))
            .thenReturn(ApplicationInfo())
        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
        `when`(cachedDevice.isConnected).thenReturn(false)

@@ -144,11 +142,11 @@ class DeviceItemFactoryTest : SysuiTestCase() {

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
    fun testSavedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() {
    fun testSavedFactory_isFilterMatched_exclusiveManagerNotEnabled_returnsTrue() {
        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
            .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray())
        `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0))
            .thenReturn(PackageInfo())
            .thenReturn(TEST_EXCLUSIVE_MANAGER.toByteArray())
        `when`(packageManager.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0))
            .thenReturn(ApplicationInfo().also { it.enabled = false })
        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
        `when`(cachedDevice.isConnected).thenReturn(false)

@@ -158,12 +156,10 @@ class DeviceItemFactoryTest : SysuiTestCase() {

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
    fun testSavedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() {
        val exclusiveManagerName =
            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
    fun testSavedFactory_isFilterMatched_exclusiveManagerNotInstalled_returnsTrue() {
        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
            .thenReturn(exclusiveManagerName.toByteArray())
        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0))
            .thenReturn(TEST_EXCLUSIVE_MANAGER.toByteArray())
        `when`(packageManager.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0))
            .thenThrow(PackageManager.NameNotFoundException("Test!"))
        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
        `when`(cachedDevice.isConnected).thenReturn(false)
@@ -228,11 +224,10 @@ class DeviceItemFactoryTest : SysuiTestCase() {
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
    fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
        val exclusiveManagerName =
            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
            .thenReturn(exclusiveManagerName.toByteArray())
        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo())
            .thenReturn(TEST_EXCLUSIVE_MANAGER.toByteArray())
        `when`(packageManager.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0))
            .thenReturn(ApplicationInfo())
        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
        `when`(bluetoothDevice.isConnected).thenReturn(true)
        audioManager.setMode(AudioManager.MODE_NORMAL)
@@ -254,11 +249,11 @@ class DeviceItemFactoryTest : SysuiTestCase() {

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
    fun testConnectedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() {
    fun testConnectedFactory_isFilterMatched_exclusiveManagerNotEnabled_returnsTrue() {
        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
            .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray())
        `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0))
            .thenReturn(PackageInfo())
            .thenReturn(TEST_EXCLUSIVE_MANAGER.toByteArray())
        `when`(packageManager.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0))
            .thenReturn(ApplicationInfo().also { it.enabled = false })
        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
        `when`(bluetoothDevice.isConnected).thenReturn(true)
        audioManager.setMode(AudioManager.MODE_NORMAL)
@@ -269,12 +264,10 @@ class DeviceItemFactoryTest : SysuiTestCase() {

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
    fun testConnectedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() {
        val exclusiveManagerName =
            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
    fun testConnectedFactory_isFilterMatched_exclusiveManagerNotInstalled_returnsTrue() {
        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
            .thenReturn(exclusiveManagerName.toByteArray())
        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0))
            .thenReturn(TEST_EXCLUSIVE_MANAGER.toByteArray())
        `when`(packageManager.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0))
            .thenThrow(PackageManager.NameNotFoundException("Test!"))
        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
        `when`(bluetoothDevice.isConnected).thenReturn(true)
@@ -317,7 +310,7 @@ class DeviceItemFactoryTest : SysuiTestCase() {
    companion object {
        const val DEVICE_NAME = "DeviceName"
        const val CONNECTION_SUMMARY = "ConnectionSummary"
        private const val FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name"
        private const val TEST_EXCLUSIVE_MANAGER = "com.test.manager"
        private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C"
    }
}