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

Commit 367e424b authored by William Escande's avatar William Escande Committed by Gerrit Code Review
Browse files

Merge "GattService: No longer start a remote service" into main

parents f2f7ead3 5bd5ff65
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -221,17 +221,6 @@
            </intent-filter>
        </service>

        <!--  Generic Attribute (GATT) Profile Service  -->
        <service android:process="@string/process"
             android:name="com.android.bluetooth.gatt.GattService"
             android:enabled="true"
             android:exported="true"
             android:permission="android.permission.ACCESS_BLUETOOTH_SHARE">
            <intent-filter>
                <action android:name="android.bluetooth.IBluetoothGatt"/>
            </intent-filter>
        </service>

        <!--  Hearing Aid Profile (HAP) client Profile Service  -->
        <service android:process="@string/process"
             android:name="com.android.bluetooth.hap.HapClientService"
+13 −82
Original line number Diff line number Diff line
@@ -79,11 +79,9 @@ import android.bluetooth.UidTraffic;
import android.companion.CompanionDeviceManager;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
@@ -371,7 +369,7 @@ public class AdapterService extends Service {
    private BassClientService mBassClientService;
    private BatteryService mBatteryService;
    private BluetoothQualityReportNativeInterface mBluetoothQualityReportNativeInterface;
    private IBluetoothGatt mBluetoothGatt;
    private GattService mGattService;

    private volatile boolean mTestModeEnabled = false;

@@ -425,8 +423,6 @@ public class AdapterService extends Service {
    private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
    private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;
    private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4;
    private static final int MESSAGE_ON_PROFILE_SERVICE_BIND = 5;
    private static final int MESSAGE_ON_PROFILE_SERVICE_UNBIND = 6;

    class AdapterServiceHandler extends Handler {
        AdapterServiceHandler(Looper looper) {
@@ -450,14 +446,6 @@ public class AdapterService extends Service {
                    verboseLog("handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
                    unregisterProfileService((ProfileService) msg.obj);
                    break;
                case MESSAGE_ON_PROFILE_SERVICE_BIND:
                    verboseLog("handleMessage() - MESSAGE_ON_PROFILE_SERVICE_BIND");
                    onGattBind((IBinder) msg.obj);
                    break;
                case MESSAGE_ON_PROFILE_SERVICE_UNBIND:
                    verboseLog("handleMessage() - MESSAGE_ON_PROFILE_SERVICE_UNBIND");
                    onGattUnbind();
                    break;
                case MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT:
                    errorLog(
                            "handleMessage() - "
@@ -497,22 +485,6 @@ public class AdapterService extends Service {
            mRegisteredProfiles.remove(profile);
        }

        private void onGattBind(IBinder service) {
            mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
            try {
                mBluetoothGatt.startService();
            } catch (RemoteException e) {
                Log.e(TAG, "onGattBind: RemoteException", e);
            }
        }

        private void onGattUnbind() {
            mBluetoothGatt = null;
            Log.e(
                    TAG,
                    "onGattUnbind: Gatt service has disconnected from AdapterService unexpectedly");
        }

        private void processProfileServiceStateChanged(ProfileService profile, int state) {
            switch (state) {
                case BluetoothAdapter.STATE_ON:
@@ -1005,47 +977,11 @@ public class AdapterService extends Service {
        }
    }

    class GattServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            String name = componentName.getClassName();
            if (DBG) {
                Log.d(TAG, "GattServiceConnection.onServiceConnected: " + name);
            }
            if (!name.equals(GattService.class.getName())) {
                Log.e(TAG, "Unknown service connected: " + name);
                return;
            }
            mHandler.obtainMessage(MESSAGE_ON_PROFILE_SERVICE_BIND, service).sendToTarget();
        }

        public void onServiceDisconnected(ComponentName componentName) {
            // Called if we unexpectedly disconnect. This should never happen.
            String name = componentName.getClassName();
            Log.e(TAG, "GattServiceConnection.onServiceDisconnected: " + name);
            if (!name.equals(GattService.class.getName())) {
                Log.e(TAG, "Unknown service disconnected: " + name);
                return;
            }
            mHandler.sendEmptyMessage(MESSAGE_ON_PROFILE_SERVICE_UNBIND);
        }
    }

    private GattServiceConnection mGattConnection = new GattServiceConnection();

    private void startGattProfileService() {
        mStartedProfiles.add(GattService.class.getSimpleName());

        Intent intent = new Intent(this, GattService.class);
        if (!bindServiceAsUser(
                intent,
                mGattConnection,
                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                UserHandle.CURRENT)) {
            // This should never happen
            // unbindService will be called during stopGattProfileService triggered by AdapterState
            Log.e(TAG, "Error while binding to gatt. This Bluetooth session will timeout");
            unbindService(mGattConnection);
        }
        mGattService = new GattService(this);
        ((ProfileService) mGattService).doStart();
    }

    private void stopGattProfileService() {
@@ -1056,15 +992,10 @@ public class AdapterService extends Service {
        }

        mStartedProfiles.remove(GattService.class.getSimpleName());

        try {
            if (mBluetoothGatt != null) {
                mBluetoothGatt.stopService();
        if (mGattService != null) {
            ((ProfileService) mGattService).doStop();
            mGattService = null;
        }
        } catch (RemoteException e) {
            Log.e(TAG, "stopGattProfileService: RemoteException", e);
        }
        unbindService(mGattConnection);
    }

    private void invalidateBluetoothGetStateCache() {
@@ -5244,6 +5175,7 @@ public class AdapterService extends Service {
            try {
                AdapterService service = getService();
                if (service != null) {
                    enforceBluetoothPrivilegedPermission(service);
                    service.unregAllGattClient(source);
                }
                receiver.send(null);
@@ -6883,16 +6815,15 @@ public class AdapterService extends Service {
    }

    IBluetoothGatt getBluetoothGatt() {
        return mBluetoothGatt;
        if (mGattService == null) {
            return null;
        }
        return IBluetoothGatt.Stub.asInterface(((ProfileService) mGattService).getBinder());
    }

    void unregAllGattClient(AttributionSource source) {
        if (mBluetoothGatt != null) {
            try {
                mBluetoothGatt.unregAll(source);
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to disconnect all apps.", e);
            }
        if (mGattService != null) {
            mGattService.unregAll(source);
        }
    }

+9 −2
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.bluetooth.btservice;

import static android.Manifest.permission.BLUETOOTH_CONNECT;

import static java.util.Objects.requireNonNull;

import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.Service;
@@ -180,6 +182,11 @@ public abstract class ProfileService extends Service {
        return mBinder;
    }

    IBinder getBinder() {
        requireNonNull(mBinder, "Binder is null. onCreate need to be called first");
        return mBinder;
    }

    @Override
    // Suppressed since this is called from framework
    @SuppressLint("AndroidFrameworkRequiresPermission")
@@ -295,7 +302,7 @@ public abstract class ProfileService extends Service {
                android.Manifest.permission.MANAGE_USERS,
                android.Manifest.permission.INTERACT_ACROSS_USERS
            })
    protected void doStart() {
    void doStart() {
        Log.v(mName, "doStart");
        if (mAdapter == null) {
            Log.w(mName, "Can't start profile service: device does not have BT");
@@ -321,7 +328,7 @@ public abstract class ProfileService extends Service {
        mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_ON);
    }

    protected void doStop() {
    void doStop() {
        Log.v(mName, "doStop");
        if (mAdapterService == null || mAdapterService.isStartedProfile(mName)) {
            Log.w(mName, "Unexpectedly do Stop, don't stop.");
+7 −38
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.bluetooth.le.ScanSettings;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.content.AttributionSource;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.PackageInfoFlags;
@@ -290,6 +291,11 @@ public class GattService extends ProfileService {
    private Handler mTestModeHandler;
    private final Object mTestModeLock = new Object();

    public GattService(Context ctx) {
        attachBaseContext(ctx);
        onCreate();
    }

    public static boolean isEnabled() {
        return BluetoothProperties.isProfileGattEnabled().orElse(true);
    }
@@ -611,34 +617,6 @@ public class GattService extends ProfileService {
            return null;
        }

        @Override
        public void startService() {
            GattService service = mService;
            if (service == null) {
                Log.e(TAG, "startService: Service is null");
                return;
            }
            if (!Utils.checkConnectPermissionForDataDelivery(
                    service, null, "GattService startService")) {
                return;
            }
            service.doStart();
        }

        @Override
        public void stopService() {
            GattService service = mService;
            if (service == null) {
                Log.e(TAG, "stopService: Service is null");
                return;
            }
            if (!Utils.checkConnectPermissionForDataDelivery(
                    service, null, "GattService stopService")) {
                return;
            }
            service.doStop();
        }

        @Override
        public void getDevicesMatchingConnectionStates(int[] states,
                AttributionSource attributionSource, SynchronousResultReceiver receiver) {
@@ -1777,15 +1755,6 @@ public class GattService extends ProfileService {
            service.disconnectAll(attributionSource);
        }

        @Override
        public void unregAll(AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.unregAll(attributionSource);
        }

        @Override
        public void numHwTrackFiltersAvailable(AttributionSource attributionSource,
                SynchronousResultReceiver receiver) {
@@ -3435,7 +3404,7 @@ public class GattService extends ProfileService {
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    void unregAll(AttributionSource attributionSource) {
    public void unregAll(AttributionSource attributionSource) {
        for (Integer appId : mClientMap.getAllAppsIds()) {
            if (DBG) {
                Log.d(TAG, "unreg:" + appId);
+19 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import androidx.test.uiautomator.UiDevice;
import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.gatt.GattService;

import org.junit.Assert;
import org.junit.rules.TestRule;
@@ -138,6 +139,21 @@ public class TestUtils {
        method.invoke(null, adapterService);
    }

    /** Helper function to mock getSystemService calls */
    public static <T> void mockGetSystemService(
            Context ctx, String serviceName, Class<T> serviceClass, T mockService) {
        when(ctx.getSystemService(eq(serviceName))).thenReturn(mockService);
        when(ctx.getSystemServiceName(eq(serviceClass))).thenReturn(serviceName);
    }

    /** Helper function to mock getSystemService calls */
    public static <T> T mockGetSystemService(
            Context ctx, String serviceName, Class<T> serviceClass) {
        T mockedService = mock(serviceClass);
        mockGetSystemService(ctx, serviceName, serviceClass, mockedService);
        return mockedService;
    }

    /**
     * Start a profile service using the given {@link ServiceTestRule} and verify through
     * {@link AdapterService#getAdapterService()} that the service is actually started within
@@ -156,6 +172,9 @@ public class TestUtils {
     */
    public static <T extends ProfileService> void startService(ServiceTestRule serviceTestRule,
            Class<T> profileServiceClass) throws TimeoutException {
        if (profileServiceClass == GattService.class) {
            Assert.assertFalse("GattService cannot be started as a service", true);
        }
        AdapterService adapterService = AdapterService.getAdapterService();
        Assert.assertNotNull("Adapter service should not be null", adapterService);
        Assert.assertTrue("AdapterService.getAdapterService() must return a mocked or spied object"
Loading