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

Commit 27ca8a77 authored by Jack He's avatar Jack He
Browse files

Initialize static service reference properly

* Change I10ea7dabcb2e0d296384d6f9a60683569bdef3f8 changes the meaning
  of isAvailable() in ProfileService. As result, many service's static
  instance references no longer get assigned properly
* This CL fixes those issue for:
    A2dpSinkService
    AvrcpControllerService
    HeadsetClientService
    HidHostService
    MapClientService
    PanService
    PbapClientService
* This CL also adds a number of tests to start and stop each
  ProfileService and do some profile specific verification such as
  verifying HeadsetClientService.getHeadsetClientService()'s return
  result is not null
* Adds a TestUtils class to include common test routines such as:
  setAdapterService(), clearAdapterService(), startService(),
  stopService()
* Remove setting to null statements in tearDown() method as JUnit4
  runner will nullify fields by default

Fixes: 72816382
Test: 1) enable all profiles in config.xml 2) runtest -j32 bluetooth
Change-Id: If39c44097d5cfbf0d606dda20e5b8cdb565b5764
parent 87bd88c1
Loading
Loading
Loading
Loading
+4 −11
Original line number Original line Diff line number Diff line
@@ -182,20 +182,17 @@ public class A2dpService extends ProfileService {
            mAvrcp.cleanup();
            mAvrcp.cleanup();
            mAvrcp = null;
            mAvrcp = null;
        }
        }
        clearA2dpService();
        // TODO(b/72948646): should be moved to stop()
        setA2dpService(null);
    }
    }


    public static synchronized A2dpService getA2dpService() {
    public static synchronized A2dpService getA2dpService() {
        if (sA2dpService == null) {
        if (sA2dpService == null) {
            if (DBG) {
            Log.w(TAG, "getA2dpService(): service is null");
                Log.d(TAG, "getA2dpService(): service is NULL");
            }
            return null;
            return null;
        }
        }
        if (!sA2dpService.isAvailable()) {
        if (!sA2dpService.isAvailable()) {
            if (DBG) {
            Log.w(TAG, "getA2dpService(): service is not available");
                Log.d(TAG, "getA2dpService(): service is not available");
            }
            return null;
            return null;
        }
        }
        return sA2dpService;
        return sA2dpService;
@@ -208,10 +205,6 @@ public class A2dpService extends ProfileService {
        sA2dpService = instance;
        sA2dpService = instance;
    }
    }


    private static synchronized void clearA2dpService() {
        sA2dpService = null;
    }

    public boolean connect(BluetoothDevice device) {
    public boolean connect(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        if (DBG) {
        if (DBG) {
+11 −30
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ public class A2dpSinkService extends ProfileService {
        if (DBG) {
        if (DBG) {
            Log.d(TAG, "stop()");
            Log.d(TAG, "stop()");
        }
        }
        setA2dpSinkService(null);
        if (mStateMachine != null) {
        if (mStateMachine != null) {
            mStateMachine.doQuit();
            mStateMachine.doQuit();
        }
        }
@@ -79,47 +80,27 @@ public class A2dpSinkService extends ProfileService {
        if (mStateMachine != null) {
        if (mStateMachine != null) {
            mStateMachine.cleanup();
            mStateMachine.cleanup();
        }
        }
        clearA2dpSinkService();
    }
    }


    //API Methods
    //API Methods


    public static synchronized A2dpSinkService getA2dpSinkService() {
    public static synchronized A2dpSinkService getA2dpSinkService() {
        if (sA2dpSinkService != null && sA2dpSinkService.isAvailable()) {
            if (DBG) {
                Log.d(TAG, "getA2dpSinkService(): returning " + sA2dpSinkService);
            }
            return sA2dpSinkService;
        }
        if (DBG) {
        if (sA2dpSinkService == null) {
        if (sA2dpSinkService == null) {
                Log.d(TAG, "getA2dpSinkService(): service is NULL");
            Log.w(TAG, "getA2dpSinkService(): service is null");
            } else if (!(sA2dpSinkService.isAvailable())) {
            return null;
                Log.d(TAG, "getA2dpSinkService(): service is not available");
            }
        }
        }
        if (!sA2dpSinkService.isAvailable()) {
            Log.w(TAG, "getA2dpSinkService(): service is not available ");
            return null;
            return null;
        }
        }
        return sA2dpSinkService;
    }


    private static synchronized void setA2dpSinkService(A2dpSinkService instance) {
    private static synchronized void setA2dpSinkService(A2dpSinkService instance) {
        if (instance != null && instance.isAvailable()) {
        if (DBG) {
        if (DBG) {
                Log.d(TAG, "setA2dpSinkService(): set to: " + sA2dpSinkService);
            Log.d(TAG, "setA2dpSinkService(): set to: " + instance);
        }
        }
        sA2dpSinkService = instance;
        sA2dpSinkService = instance;
        } else {
            if (DBG) {
                if (sA2dpSinkService == null) {
                    Log.d(TAG, "setA2dpSinkService(): service not available");
                } else if (!sA2dpSinkService.isAvailable()) {
                    Log.d(TAG, "setA2dpSinkService(): service is cleaning up");
                }
            }
        }
    }

    private static synchronized void clearA2dpSinkService() {
        sA2dpSinkService = null;
    }
    }


    public boolean connect(BluetoothDevice device) {
    public boolean connect(BluetoothDevice device) {
+11 −29
Original line number Original line Diff line number Diff line
@@ -222,6 +222,7 @@ public class AvrcpControllerService extends ProfileService {


    @Override
    @Override
    protected boolean stop() {
    protected boolean stop() {
        setAvrcpControllerService(null);
        if (mAvrcpCtSm != null) {
        if (mAvrcpCtSm != null) {
            mAvrcpCtSm.doQuit();
            mAvrcpCtSm.doQuit();
        }
        }
@@ -231,41 +232,22 @@ public class AvrcpControllerService extends ProfileService {
    //API Methods
    //API Methods


    public static synchronized AvrcpControllerService getAvrcpControllerService() {
    public static synchronized AvrcpControllerService getAvrcpControllerService() {
        if (sAvrcpControllerService != null && sAvrcpControllerService.isAvailable()) {
            if (DBG) {
                Log.d(TAG, "getAvrcpControllerService(): returning " + sAvrcpControllerService);
            }
            return sAvrcpControllerService;
        }
        if (DBG) {
        if (sAvrcpControllerService == null) {
        if (sAvrcpControllerService == null) {
                Log.d(TAG, "getAvrcpControllerService(): service is NULL");
            Log.w(TAG, "getAvrcpControllerService(): service is null");
            } else if (!(sAvrcpControllerService.isAvailable())) {
            return null;
                Log.d(TAG, "getAvrcpControllerService(): service is not available");
            }
        }
        }
        if (!sAvrcpControllerService.isAvailable()) {
            Log.w(TAG, "getAvrcpControllerService(): service is not available ");
            return null;
            return null;
        }
        }
        return sAvrcpControllerService;
    }


    private static synchronized void setAvrcpControllerService(AvrcpControllerService instance) {
    private static synchronized void setAvrcpControllerService(AvrcpControllerService instance) {
        if (instance != null && instance.isAvailable()) {
        if (DBG) {
        if (DBG) {
                Log.d(TAG, "setAvrcpControllerService(): set to: " + sAvrcpControllerService);
            Log.d(TAG, "setAvrcpControllerService(): set to: " + instance);
        }
        }
        sAvrcpControllerService = instance;
        sAvrcpControllerService = instance;
        } else {
            if (DBG) {
                if (instance == null) {
                    Log.d(TAG, "setAvrcpControllerService(): service not available");
                } else if (!instance.isAvailable()) {
                    Log.d(TAG, "setAvrcpControllerService(): service is cleaning up");
                }
            }
        }
    }

    private static synchronized void clearAvrcpControllerService() {
        sAvrcpControllerService = null;
    }
    }


    public synchronized List<BluetoothDevice> getConnectedDevices() {
    public synchronized List<BluetoothDevice> getConnectedDevices() {
+30 −0
Original line number Original line Diff line number Diff line
@@ -171,6 +171,8 @@ public class GattService extends ProfileService {
    private ScanManager mScanManager;
    private ScanManager mScanManager;
    private AppOpsManager mAppOps;
    private AppOpsManager mAppOps;


    private static GattService sGattService;

    /**
    /**
     * Reliable write queue
     * Reliable write queue
     */
     */
@@ -201,6 +203,7 @@ public class GattService extends ProfileService {
        mPeriodicScanManager = new PeriodicScanManager(AdapterService.getAdapterService());
        mPeriodicScanManager = new PeriodicScanManager(AdapterService.getAdapterService());
        mPeriodicScanManager.start();
        mPeriodicScanManager.start();


        setGattService(this);
        return true;
        return true;
    }
    }


@@ -209,6 +212,7 @@ public class GattService extends ProfileService {
        if (DBG) {
        if (DBG) {
            Log.d(TAG, "stop()");
            Log.d(TAG, "stop()");
        }
        }
        setGattService(null);
        mScannerMap.clear();
        mScannerMap.clear();
        mClientMap.clear();
        mClientMap.clear();
        mServerMap.clear();
        mServerMap.clear();
@@ -243,6 +247,32 @@ public class GattService extends ProfileService {
        }
        }
    }
    }



    /**
     * Get the current instance of {@link GattService}
     *
     * @return current instance of {@link GattService}
     */
    @VisibleForTesting
    public static synchronized GattService getGattService() {
        if (sGattService == null) {
            Log.w(TAG, "getGattService(): service is null");
            return null;
        }
        if (!sGattService.isAvailable()) {
            Log.w(TAG, "getGattService(): service is not available");
            return null;
        }
        return sGattService;
    }

    private static synchronized void setGattService(GattService instance) {
        if (DBG) {
            Log.d(TAG, "setGattService(): set to: " + instance);
        }
        sGattService = instance;
    }

    boolean permissionCheck(UUID uuid) {
    boolean permissionCheck(UUID uuid) {
        return !(isRestrictedCharUuid(uuid) && (0 != checkCallingOrSelfPermission(
        return !(isRestrictedCharUuid(uuid) && (0 != checkCallingOrSelfPermission(
                BLUETOOTH_PRIVILEGED)));
                BLUETOOTH_PRIVILEGED)));
+30 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.RemoteException;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.Log;


import com.android.bluetooth.Utils;
import com.android.bluetooth.Utils;
@@ -67,6 +68,8 @@ public class HealthService extends ProfileService {
    private static final int MESSAGE_APP_REGISTRATION_CALLBACK = 11;
    private static final int MESSAGE_APP_REGISTRATION_CALLBACK = 11;
    private static final int MESSAGE_CHANNEL_STATE_CALLBACK = 12;
    private static final int MESSAGE_CHANNEL_STATE_CALLBACK = 12;


    private static HealthService sHealthService;

    static {
    static {
        classInitNative();
        classInitNative();
    }
    }
@@ -89,11 +92,13 @@ public class HealthService extends ProfileService {
        mHandler = new HealthServiceMessageHandler(looper);
        mHandler = new HealthServiceMessageHandler(looper);
        initializeNative();
        initializeNative();
        mNativeAvailable = true;
        mNativeAvailable = true;
        setHealthService(this);
        return true;
        return true;
    }
    }


    @Override
    @Override
    protected boolean stop() {
    protected boolean stop() {
        setHealthService(null);
        if (mHandler != null) {
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler.removeCallbacksAndMessages(null);
            Looper looper = mHandler.getLooper();
            Looper looper = mHandler.getLooper();
@@ -139,6 +144,31 @@ public class HealthService extends ProfileService {
        }
        }
    }
    }


    /**
     * Get a static reference to the current health service instance
     *
     * @return current health service instance
     */
    @VisibleForTesting
    public static synchronized HealthService getHealthService() {
        if (sHealthService == null) {
            Log.w(TAG, "getHealthService(): service is null");
            return null;
        }
        if (!sHealthService.isAvailable()) {
            Log.w(TAG, "getHealthService(): service is not available");
            return null;
        }
        return sHealthService;
    }

    private static synchronized void setHealthService(HealthService instance) {
        if (DBG) {
            Log.d(TAG, "setHealthService(): set to: " + instance);
        }
        sHealthService = instance;
    }

    private final class HealthServiceMessageHandler extends Handler {
    private final class HealthServiceMessageHandler extends Handler {
        private HealthServiceMessageHandler(Looper looper) {
        private HealthServiceMessageHandler(Looper looper) {
            super(looper);
            super(looper);
Loading