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

Commit cb5ddfda authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Pbap use profileConnector, resolveSystemService api fix" am: 4548fa72...

Merge "Pbap use profileConnector, resolveSystemService api fix" am: 4548fa72 am: fff72939 am: 4296ee7d

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1916517

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

import java.util.ArrayList;
@@ -96,10 +91,6 @@ public class BluetoothPbap implements BluetoothProfile {
    public static final String 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;

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

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

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

        // 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;
                }
            }
        }
        mProfileConnector.connect(context, listener);
    }

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

    private IBluetoothPbap getService() {
        return (IBluetoothPbap) mProfileConnector.getService();
    }

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

package android.bluetooth;

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

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

    private @Nullable ComponentName resolveSystemService(@NonNull Intent intent,
            @NonNull PackageManager pm, @PackageManager.ComponentInfoFlags int flags) {
        List<ResolveInfo> results = pm.queryIntentServices(intent, flags);
        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() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            logDebug("Proxy object connected");
@@ -99,8 +127,8 @@ public abstract class BluetoothProfileConnector<T> {
                mCloseGuard.open("doUnbind");
                try {
                    Intent intent = new Intent(mServiceName);
                    ComponentName comp = intent.resolveSystemService(
                            mContext.getPackageManager(), 0);
                    ComponentName comp = resolveSystemService(intent, mContext.getPackageManager(),
                            0);
                    intent.setComponent(comp);
                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
                            UserHandle.CURRENT)) {