Loading android/app/aidl/android/bluetooth/IBluetooth.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -313,4 +313,10 @@ interface IBluetooth @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") oneway void getProfile(int profile, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") oneway void setActiveAudioDevicePolicy(in BluetoothDevice device, int activeAudioDevicePolicy, in AttributionSource source, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") oneway void getActiveAudioDevicePolicy(in BluetoothDevice device, in AttributionSource source, in SynchronousResultReceiver receiver); } android/app/src/com/android/bluetooth/btservice/AdapterService.java +77 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,6 @@ import com.android.bluetooth.csip.CsipSetCoordinatorService; import com.android.bluetooth.flags.FeatureFlagsImpl; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.hap.HapClientService; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.hfp.HeadsetService; Loading @@ -136,6 +135,7 @@ import com.android.bluetooth.hfpclient.HeadsetClientService; import com.android.bluetooth.hid.HidDeviceService; import com.android.bluetooth.hid.HidHostService; import com.android.bluetooth.le_audio.LeAudioService; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.map.BluetoothMapService; import com.android.bluetooth.mapclient.MapClientService; import com.android.bluetooth.mcp.McpService; Loading Loading @@ -5389,6 +5389,82 @@ public class AdapterService extends Service { return service.getProfile(profileId); } @Override public void setActiveAudioDevicePolicy( BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(setActiveAudioDevicePolicy(device, activeAudioDevicePolicy, source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission( allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private int setActiveAudioDevicePolicy( BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) { AdapterService service = getService(); if (service == null) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; } if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; } if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { throw new IllegalArgumentException("device cannot have an invalid address"); } if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } enforceBluetoothPrivilegedPermission(service); return service.mDatabaseManager.setActiveAudioDevicePolicy( device, activeAudioDevicePolicy); } @Override public void getActiveAudioDevicePolicy( BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(getActiveAudioDevicePolicy(device, source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission( allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) { AdapterService service = getService(); if (service == null) { return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) { throw new IllegalStateException( "Caller is not the system or part of the active/managed user"); } if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { throw new IllegalArgumentException("device cannot have an invalid address"); } if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } enforceBluetoothPrivilegedPermission(service); return service.mDatabaseManager.getActiveAudioDevicePolicy(device); } } /** Loading android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java +54 −0 Original line number Diff line number Diff line Loading @@ -1014,6 +1014,60 @@ public class DatabaseManager { return modeToProfileBundle; } /** * Set the device active audio policy. See {@link * BluetoothDevice#setActiveAudioDevicePolicy(activeAudioDevicePolicy)} for more details. * * @param device is the remote device for which we are setting the active audio device policy. * @param activeAudioDevicePolicy active audio device policy. * @return whether the policy was set properly */ public int setActiveAudioDevicePolicy(BluetoothDevice device, int activeAudioDevicePolicy) { synchronized (mMetadataCache) { String address = device.getAddress(); if (!mMetadataCache.containsKey(address)) { Log.e(TAG, "device is not bonded"); return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; } Metadata metadata = mMetadataCache.get(address); Log.i( TAG, "Updating active_audio_device_policy setting for " + "device " + device + " to: " + activeAudioDevicePolicy); metadata.active_audio_device_policy = activeAudioDevicePolicy; updateDatabase(metadata); } return BluetoothStatusCodes.SUCCESS; } /** * Get the active audio device policy for this device. See {@link * BluetoothDevice#getActiveAudioDevicePolicy()} for more details. * * @param device is the device for which we want to get the policy * @return active audio device policy for this device */ public int getActiveAudioDevicePolicy(BluetoothDevice device) { synchronized (mMetadataCache) { String address = device.getAddress(); if (!mMetadataCache.containsKey(address)) { Log.e(TAG, "device is not bonded"); return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } Metadata metadata = mMetadataCache.get(address); return metadata.active_audio_device_policy; } } /** * Get the {@link Looper} for the handler thread. This is used in testing and helper * objects Loading android/app/src/com/android/bluetooth/btservice/storage/Metadata.java +4 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,9 @@ public class Metadata { */ public int preferred_duplex_profile; /** This is used to indicate whether device's active audio policy */ public int active_audio_device_policy; Metadata(String address) { this(address, false, false); } Loading @@ -96,6 +99,7 @@ public class Metadata { audioPolicyMetadata = new AudioPolicyEntity(); preferred_output_only_profile = 0; preferred_duplex_profile = 0; active_audio_device_policy = BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } static final class Builder { Loading android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java +23 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import java.util.List; /** MetadataDatabase is a Room database stores Bluetooth persistence data */ @Database( entities = {Metadata.class}, version = 119) version = 120) public abstract class MetadataDatabase extends RoomDatabase { /** The metadata database file name */ public static final String DATABASE_NAME = "bluetooth_db"; Loading Loading @@ -69,6 +69,7 @@ public abstract class MetadataDatabase extends RoomDatabase { .addMigrations(MIGRATION_116_117) .addMigrations(MIGRATION_117_118) .addMigrations(MIGRATION_118_119) .addMigrations(MIGRATION_119_120) .allowMainThreadQueries() .build(); } Loading Loading @@ -649,4 +650,25 @@ public abstract class MetadataDatabase extends RoomDatabase { } } }; @VisibleForTesting static final Migration MIGRATION_119_120 = new Migration(119, 120) { @Override public void migrate(SupportSQLiteDatabase database) { try { database.execSQL( "ALTER TABLE metadata ADD COLUMN" + " `active_audio_device_policy` INTEGER NOT NULL" + " DEFAULT 0"); } catch (SQLException ex) { // Check if user has new schema, but is just missing the version update Cursor cursor = database.query("SELECT * FROM metadata"); if (cursor == null || cursor.getColumnIndex("active_audio_device_policy") == -1) { throw ex; } } } }; } Loading
android/app/aidl/android/bluetooth/IBluetooth.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -313,4 +313,10 @@ interface IBluetooth @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") oneway void getProfile(int profile, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") oneway void setActiveAudioDevicePolicy(in BluetoothDevice device, int activeAudioDevicePolicy, in AttributionSource source, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") oneway void getActiveAudioDevicePolicy(in BluetoothDevice device, in AttributionSource source, in SynchronousResultReceiver receiver); }
android/app/src/com/android/bluetooth/btservice/AdapterService.java +77 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,6 @@ import com.android.bluetooth.csip.CsipSetCoordinatorService; import com.android.bluetooth.flags.FeatureFlagsImpl; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.hap.HapClientService; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.hfp.HeadsetService; Loading @@ -136,6 +135,7 @@ import com.android.bluetooth.hfpclient.HeadsetClientService; import com.android.bluetooth.hid.HidDeviceService; import com.android.bluetooth.hid.HidHostService; import com.android.bluetooth.le_audio.LeAudioService; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.map.BluetoothMapService; import com.android.bluetooth.mapclient.MapClientService; import com.android.bluetooth.mcp.McpService; Loading Loading @@ -5389,6 +5389,82 @@ public class AdapterService extends Service { return service.getProfile(profileId); } @Override public void setActiveAudioDevicePolicy( BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(setActiveAudioDevicePolicy(device, activeAudioDevicePolicy, source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission( allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private int setActiveAudioDevicePolicy( BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) { AdapterService service = getService(); if (service == null) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; } if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; } if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { throw new IllegalArgumentException("device cannot have an invalid address"); } if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } enforceBluetoothPrivilegedPermission(service); return service.mDatabaseManager.setActiveAudioDevicePolicy( device, activeAudioDevicePolicy); } @Override public void getActiveAudioDevicePolicy( BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(getActiveAudioDevicePolicy(device, source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission( allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) { AdapterService service = getService(); if (service == null) { return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) { throw new IllegalStateException( "Caller is not the system or part of the active/managed user"); } if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { throw new IllegalArgumentException("device cannot have an invalid address"); } if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } enforceBluetoothPrivilegedPermission(service); return service.mDatabaseManager.getActiveAudioDevicePolicy(device); } } /** Loading
android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java +54 −0 Original line number Diff line number Diff line Loading @@ -1014,6 +1014,60 @@ public class DatabaseManager { return modeToProfileBundle; } /** * Set the device active audio policy. See {@link * BluetoothDevice#setActiveAudioDevicePolicy(activeAudioDevicePolicy)} for more details. * * @param device is the remote device for which we are setting the active audio device policy. * @param activeAudioDevicePolicy active audio device policy. * @return whether the policy was set properly */ public int setActiveAudioDevicePolicy(BluetoothDevice device, int activeAudioDevicePolicy) { synchronized (mMetadataCache) { String address = device.getAddress(); if (!mMetadataCache.containsKey(address)) { Log.e(TAG, "device is not bonded"); return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; } Metadata metadata = mMetadataCache.get(address); Log.i( TAG, "Updating active_audio_device_policy setting for " + "device " + device + " to: " + activeAudioDevicePolicy); metadata.active_audio_device_policy = activeAudioDevicePolicy; updateDatabase(metadata); } return BluetoothStatusCodes.SUCCESS; } /** * Get the active audio device policy for this device. See {@link * BluetoothDevice#getActiveAudioDevicePolicy()} for more details. * * @param device is the device for which we want to get the policy * @return active audio device policy for this device */ public int getActiveAudioDevicePolicy(BluetoothDevice device) { synchronized (mMetadataCache) { String address = device.getAddress(); if (!mMetadataCache.containsKey(address)) { Log.e(TAG, "device is not bonded"); return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } Metadata metadata = mMetadataCache.get(address); return metadata.active_audio_device_policy; } } /** * Get the {@link Looper} for the handler thread. This is used in testing and helper * objects Loading
android/app/src/com/android/bluetooth/btservice/storage/Metadata.java +4 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,9 @@ public class Metadata { */ public int preferred_duplex_profile; /** This is used to indicate whether device's active audio policy */ public int active_audio_device_policy; Metadata(String address) { this(address, false, false); } Loading @@ -96,6 +99,7 @@ public class Metadata { audioPolicyMetadata = new AudioPolicyEntity(); preferred_output_only_profile = 0; preferred_duplex_profile = 0; active_audio_device_policy = BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; } static final class Builder { Loading
android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java +23 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import java.util.List; /** MetadataDatabase is a Room database stores Bluetooth persistence data */ @Database( entities = {Metadata.class}, version = 119) version = 120) public abstract class MetadataDatabase extends RoomDatabase { /** The metadata database file name */ public static final String DATABASE_NAME = "bluetooth_db"; Loading Loading @@ -69,6 +69,7 @@ public abstract class MetadataDatabase extends RoomDatabase { .addMigrations(MIGRATION_116_117) .addMigrations(MIGRATION_117_118) .addMigrations(MIGRATION_118_119) .addMigrations(MIGRATION_119_120) .allowMainThreadQueries() .build(); } Loading Loading @@ -649,4 +650,25 @@ public abstract class MetadataDatabase extends RoomDatabase { } } }; @VisibleForTesting static final Migration MIGRATION_119_120 = new Migration(119, 120) { @Override public void migrate(SupportSQLiteDatabase database) { try { database.execSQL( "ALTER TABLE metadata ADD COLUMN" + " `active_audio_device_policy` INTEGER NOT NULL" + " DEFAULT 0"); } catch (SQLException ex) { // Check if user has new schema, but is just missing the version update Cursor cursor = database.query("SELECT * FROM metadata"); if (cursor == null || cursor.getColumnIndex("active_audio_device_policy") == -1) { throw ex; } } } }; }