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

Commit 3b8097fb authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Gerrit Code Review
Browse files

Merge "Media Control Profile for LE Audio"

parents 313e8806 da278920
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -371,7 +371,7 @@
             android:exported="true"
             android:enabled="@bool/profile_supported_mcp_server">
            <intent-filter>
                <action android:name="android.bluetooth.IBluetoothMcpService" />
                <action android:name="android.bluetooth.IBluetoothMcpServiceManager" />
            </intent-filter>
        </service>
        <service
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
 * limitations under the License.
 */

package com.android.le_audio;
package com.android.bluetooth.le_audio;

import java.util.SortedSet;
import java.util.TreeSet;
+13 −0
Original line number Diff line number Diff line
@@ -36,7 +36,9 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.mcp.McpService;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
@@ -62,6 +64,7 @@ public class LeAudioService extends ProfileService {
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
    private BluetoothDevice mPreviousAudioDevice;
    ServiceFactory mServiceFactory = new ServiceFactory();

    LeAudioNativeInterface mLeAudioNativeInterface;
    AudioManager mAudioManager;
@@ -580,6 +583,11 @@ public class LeAudioService extends ProfileService {
            if (!mGroupIdConnectedMap.getOrDefault(myGroupId, false)) {
                mGroupIdConnectedMap.put(myGroupId, true);
            }

            McpService mcpService = mServiceFactory.getMcpService();
            if (mcpService != null) {
                mcpService.setDeviceAuthorized(device, true);
            }
        }
        if (fromState == BluetoothProfile.STATE_CONNECTED && getConnectedDevices().isEmpty()) {
            setActiveDevice(null);
@@ -595,6 +603,11 @@ public class LeAudioService extends ProfileService {
                }
                removeStateMachine(device);
            }

            McpService mcpService = mServiceFactory.getMcpService();
            if (mcpService != null) {
                mcpService.setDeviceAuthorized(device, false);
            }
        }
    }

+36 −8
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.ProfileService;

import java.util.HashMap;
import java.util.Map;

/**
 * Provides Media Control Profile, as a service in the Bluetooth application.
 * @hide
@@ -31,10 +34,13 @@ import com.android.bluetooth.btservice.ProfileService;
public class McpService extends ProfileService {
    private static final boolean DBG = true;
    private static final boolean VDBG = false;
    private static final String TAG = "McpService";
    private static final String TAG = "BluetoothMcpService";

    private static McpService sMcpService;

    private static MediaControlProfile mGmcs;
    private Map<BluetoothDevice, Integer> mDeviceAuthorizations = new HashMap<>();

    private static synchronized void setMcpService(McpService instance) {
        if (VDBG) {
            Log.d(TAG, "setMcpService(): set to: " + instance);
@@ -55,6 +61,10 @@ public class McpService extends ProfileService {
        return sMcpService;
    }

    public static void setMediaControlProfileForTesting(MediaControlProfile mediaControlProfile) {
        mGmcs = mediaControlProfile;
    }

    @Override
    protected IProfileServiceBinder initBinder() {
        return new BluetoothMcpServiceBinder(this);
@@ -80,6 +90,13 @@ public class McpService extends ProfileService {
        // Mark service as started
        setMcpService(this);

        if (mGmcs == null) {
            // Initialize the Media Control Service Server
            mGmcs = new MediaControlProfile(this);
            // Requires this service to be already started thus we have to make it an async call
            this.getMainThreadHandler().post(() -> mGmcs.init());
        }

        return true;
    }

@@ -94,9 +111,12 @@ public class McpService extends ProfileService {
            return true;
        }

        if (mGmcs != null) {
            mGmcs.cleanup();
        }

        // Mark service as stopped
        setMcpService(null);

        return true;
    }

@@ -108,17 +128,21 @@ public class McpService extends ProfileService {
    }

    public void onDeviceUnauthorized(BluetoothDevice device) {
        // TODO: For now just reject authorization for other than LeAudio device already authorized.
        //       Consider intent based authorization mechanism for non-LeAudio devices.
        setDeviceAuthorized(device, false);
    }

    public int getDeviceAuthorization(BluetoothDevice device) {
        return BluetoothDevice.ACCESS_ALLOWED;
    }
    public void setDeviceAuthorized(BluetoothDevice device, boolean isAuthorized) {
        int authorization = isAuthorized ? BluetoothDevice.ACCESS_ALLOWED
                : BluetoothDevice.ACCESS_REJECTED;
        mDeviceAuthorizations.put(device, authorization);

    void setDeviceAuthorized(BluetoothDevice device, boolean isAuthorized) {
        mGmcs.onDeviceAuthorizationSet(device);
    }

    public int getDeviceAuthorization(BluetoothDevice device) {
        // TODO: For now just reject authorization for other than LeAudio device already authorized.
        //       Consider intent based authorization mechanism for non-LeAudio devices.
        return mDeviceAuthorizations.getOrDefault(device, BluetoothDevice.ACCESS_UNKNOWN);
    }

    /**
@@ -153,6 +177,9 @@ public class McpService extends ProfileService {

        @Override
        public void cleanup() {
            if (mService != null) {
                mService.cleanup();
            }
            mService = null;
        }
    }
@@ -160,5 +187,6 @@ public class McpService extends ProfileService {
    @Override
    public void dump(StringBuilder sb) {
        super.dump(sb);
        mGmcs.dump(sb);
    }
}
+11 −3
Original line number Diff line number Diff line
@@ -903,8 +903,15 @@ public class MediaControlGattService implements MediaControlGattServiceInterface

        if (mBluetoothGattServer == null) {
            BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
            mBluetoothGattServer = new BluetoothGattServerProxy(
                    manager.openGattServer(mContext, mServerCallback), manager);
            BluetoothGattServer server = manager.openGattServer(mContext, mServerCallback);
            if (server == null) {
                Log.e(TAG, "Failed to start BluetoothGattServer for MCP");
                //TODO: This now effectively makes MCP unusable, but fixes tests
                // Handle this error more gracefully, verify BluetoothInstrumentationTests
                // are passing after fix is applied
                return false;
            }
            mBluetoothGattServer = new BluetoothGattServerProxy(server, manager);
        }

        mGattService =
@@ -1237,7 +1244,8 @@ public class MediaControlGattService implements MediaControlGattServiceInterface
        if (DBG) {
            Log.d(TAG, "Destroy");
        }
        if (mBluetoothGattServer.removeService(mGattService)) {
        if (mBluetoothGattServer != null
                && mBluetoothGattServer.removeService(mGattService)) {
            if (mCallbacks != null) {
                mCallbacks.onServiceInstanceUnregistered(ServiceStatus.OK);
            }
Loading