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

Commit 3fe4b24d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Pbap use profileConnector, resolveSystemService api fix"

parents e0428e79 0c86889d
Loading
Loading
Loading
Loading
+20 −115
Original line number Original line Diff line number Diff line
@@ -25,15 +25,10 @@ import android.annotation.SystemApi;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AttributionSource;
import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Build;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Log;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -96,10 +91,6 @@ public class BluetoothPbap implements BluetoothProfile {
    public static final String ACTION_CONNECTION_STATE_CHANGED =
    public static final String ACTION_CONNECTION_STATE_CHANGED =
            "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
            "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";


    private volatile IBluetoothPbap mService;
    private final Context mContext;
    private ServiceListener mServiceListener;
    private final BluetoothAdapter mAdapter;
    private final AttributionSource mAttributionSource;
    private final AttributionSource mAttributionSource;


    /** @hide */
    /** @hide */
@@ -113,16 +104,13 @@ public class BluetoothPbap implements BluetoothProfile {
     */
     */
    public static final int RESULT_CANCELED = 2;
    public static final int RESULT_CANCELED = 2;


    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private BluetoothAdapter mAdapter;
    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
    private final BluetoothProfileConnector<IBluetoothPbap> mProfileConnector =
            new IBluetoothStateChangeCallback.Stub() {
            new BluetoothProfileConnector(this, BluetoothProfile.PBAP, "BluetoothPbap",
                public void onBluetoothStateChange(boolean up) {
                    IBluetoothPbap.class.getName()) {
                    log("onBluetoothStateChange: up=" + up);
                @Override
                    if (!up) {
                public IBluetoothPbap getServiceInterface(IBinder service) {
                        doUnbind();
                    return IBluetoothPbap.Stub.asInterface(service);
                    } else {
                        doBind();
                    }
                }
                }
    };
    };


@@ -131,69 +119,10 @@ public class BluetoothPbap implements BluetoothProfile {
     *
     *
     * @hide
     * @hide
     */
     */
    public BluetoothPbap(Context context, ServiceListener l, BluetoothAdapter adapter) {
    public BluetoothPbap(Context context, ServiceListener listener, BluetoothAdapter adapter) {
        mContext = context;
        mServiceListener = l;
        mAdapter = adapter;
        mAdapter = adapter;
        mAttributionSource = adapter.getAttributionSource();
        mAttributionSource = adapter.getAttributionSource();

        mProfileConnector.connect(context, listener);
        // Preserve legacy compatibility where apps were depending on
        // registerStateChangeCallback() performing a permissions check which
        // has been relaxed in modern platform versions
        if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
                && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
                        != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Need BLUETOOTH permission");
        }

        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException re) {
                Log.e(TAG, "", re);
            }
        }
        doBind();
    }

    @SuppressLint("AndroidFrameworkRequiresPermission")
    boolean doBind() {
        synchronized (mConnection) {
            try {
                if (mService == null) {
                    log("Binding service...");
                    Intent intent = new Intent(IBluetoothPbap.class.getName());
                    ComponentName comp = intent.resolveSystemService(
                            mContext.getPackageManager(), 0);
                    intent.setComponent(comp);
                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
                            UserHandle.CURRENT)) {
                        Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
                        return false;
                    }
                }
            } catch (SecurityException se) {
                Log.e(TAG, "", se);
                return false;
            }
        }
        return true;
    }

    private void doUnbind() {
        synchronized (mConnection) {
            if (mService != null) {
                log("Unbinding service...");
                try {
                    mContext.unbindService(mConnection);
                } catch (IllegalArgumentException ie) {
                    Log.e(TAG, "", ie);
                } finally {
                    mService = null;
                }
            }
        }
    }
    }


    /** @hide */
    /** @hide */
@@ -214,16 +143,11 @@ public class BluetoothPbap implements BluetoothProfile {
     * @hide
     * @hide
     */
     */
    public synchronized void close() {
    public synchronized void close() {
        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        mProfileConnector.disconnect();
        if (mgr != null) {
            try {
                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException re) {
                Log.e(TAG, "", re);
            }
    }
    }
        doUnbind();

        mServiceListener = null;
    private IBluetoothPbap getService() {
        return (IBluetoothPbap) mProfileConnector.getService();
    }
    }


    /**
    /**
@@ -236,7 +160,7 @@ public class BluetoothPbap implements BluetoothProfile {
    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
    public List<BluetoothDevice> getConnectedDevices() {
    public List<BluetoothDevice> getConnectedDevices() {
        log("getConnectedDevices()");
        log("getConnectedDevices()");
        final IBluetoothPbap service = mService;
        final IBluetoothPbap service = getService();
        if (service == null) {
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            Log.w(TAG, "Proxy not attached to service");
            return new ArrayList<BluetoothDevice>();
            return new ArrayList<BluetoothDevice>();
@@ -265,7 +189,7 @@ public class BluetoothPbap implements BluetoothProfile {
    public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
    public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
        log("getConnectionState: device=" + device);
        log("getConnectionState: device=" + device);
        try {
        try {
            final IBluetoothPbap service = mService;
            final IBluetoothPbap service = getService();
            if (service != null && isEnabled() && isValidDevice(device)) {
            if (service != null && isEnabled() && isValidDevice(device)) {
                return service.getConnectionState(device, mAttributionSource);
                return service.getConnectionState(device, mAttributionSource);
            }
            }
@@ -289,7 +213,7 @@ public class BluetoothPbap implements BluetoothProfile {
    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states));
        log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states));
        final IBluetoothPbap service = mService;
        final IBluetoothPbap service = getService();
        if (service == null) {
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            Log.w(TAG, "Proxy not attached to service");
            return new ArrayList<BluetoothDevice>();
            return new ArrayList<BluetoothDevice>();
@@ -330,7 +254,7 @@ public class BluetoothPbap implements BluetoothProfile {
            @ConnectionPolicy int connectionPolicy) {
            @ConnectionPolicy int connectionPolicy) {
        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
        try {
        try {
            final IBluetoothPbap service = mService;
            final IBluetoothPbap service = getService();
            if (service != null && isEnabled()
            if (service != null && isEnabled()
                    && isValidDevice(device)) {
                    && isValidDevice(device)) {
                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
@@ -359,7 +283,7 @@ public class BluetoothPbap implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean disconnect(BluetoothDevice device) {
    public boolean disconnect(BluetoothDevice device) {
        log("disconnect()");
        log("disconnect()");
        final IBluetoothPbap service = mService;
        final IBluetoothPbap service = getService();
        if (service == null) {
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            Log.w(TAG, "Proxy not attached to service");
            return false;
            return false;
@@ -373,25 +297,6 @@ public class BluetoothPbap implements BluetoothProfile {
        return false;
        return false;
    }
    }


    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private final ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            log("Proxy object connected");
            mService = IBluetoothPbap.Stub.asInterface(service);
            if (mServiceListener != null) {
                mServiceListener.onServiceConnected(BluetoothProfile.PBAP, BluetoothPbap.this);
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            log("Proxy object disconnected");
            doUnbind();
            if (mServiceListener != null) {
                mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP);
            }
        }
    };

    private boolean isEnabled() {
    private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
        return false;
+30 −2
Original line number Original line Diff line number Diff line
@@ -16,12 +16,16 @@


package android.bluetooth;
package android.bluetooth;


import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Build;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -29,6 +33,7 @@ import android.os.UserHandle;
import android.util.CloseGuard;
import android.util.CloseGuard;
import android.util.Log;
import android.util.Log;


import java.util.List;
/**
/**
 * Connector for Bluetooth profile proxies to bind manager service and
 * Connector for Bluetooth profile proxies to bind manager service and
 * profile services
 * profile services
@@ -57,6 +62,30 @@ public abstract class BluetoothProfileConnector<T> {
        }
        }
    };
    };


    private @Nullable ComponentName resolveSystemService(@NonNull Intent intent,
            @NonNull PackageManager pm) {
        List<ResolveInfo> results = pm.queryIntentServices(intent,
                PackageManager.ResolveInfoFlags.of(0));
        if (results == null) {
            return null;
        }
        ComponentName comp = null;
        for (int i = 0; i < results.size(); i++) {
            ResolveInfo ri = results.get(i);
            if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                continue;
            }
            ComponentName foundComp = new ComponentName(ri.serviceInfo.applicationInfo.packageName,
                    ri.serviceInfo.name);
            if (comp != null) {
                throw new IllegalStateException("Multiple system services handle " + intent
                        + ": " + comp + ", " + foundComp);
            }
            comp = foundComp;
        }
        return comp;
    }

    private final ServiceConnection mConnection = new ServiceConnection() {
    private final ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
        public void onServiceConnected(ComponentName className, IBinder service) {
            logDebug("Proxy object connected");
            logDebug("Proxy object connected");
@@ -99,8 +128,7 @@ public abstract class BluetoothProfileConnector<T> {
                mCloseGuard.open("doUnbind");
                mCloseGuard.open("doUnbind");
                try {
                try {
                    Intent intent = new Intent(mServiceName);
                    Intent intent = new Intent(mServiceName);
                    ComponentName comp = intent.resolveSystemService(
                    ComponentName comp = resolveSystemService(intent, mContext.getPackageManager());
                            mContext.getPackageManager(), 0);
                    intent.setComponent(comp);
                    intent.setComponent(comp);
                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
                            UserHandle.CURRENT)) {
                            UserHandle.CURRENT)) {