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

Commit 6cb4ec00 authored by Benjamin Franz's avatar Benjamin Franz
Browse files

Allow managed profile apps to use some bluetooth functionality.

Adding a function that checks whether the calling user is the foreground
user or a managed profile associated to this user. This function is
deployed in selected spots to give managed profile apps access to some
part of the bluetooth functionality including the HeadsetService.

Bug: 16968338
Change-Id: Ib0db0847cf361b449484195553725c38ede3b618
parent 9f99e629
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -19,10 +19,14 @@ package com.android.bluetooth;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.ParcelUuid;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import java.io.IOException;
@@ -208,6 +212,33 @@ final public class Utils {
        return ok;
    }

    public static boolean checkCallerAllowManagedProfiles(Context mContext) {
        if (mContext == null) {
            return checkCaller();
        }
        boolean ok;
        // Get the caller's user id and if it's a managed profile, get it's parents
        // id, then clear the calling identity
        // which will be restored in the finally clause.
        int callingUser = UserHandle.getCallingUserId();
        long ident = Binder.clearCallingIdentity();
        try {
            UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
            UserInfo ui = um.getProfileParent(callingUser);
            int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
            // With calling identity cleared the current user is the foreground user.
            int foregroundUser = ActivityManager.getCurrentUser();
            ok = (foregroundUser == callingUser) ||
                    (foregroundUser == parentUser);
        } catch (Exception ex) {
            Log.e(TAG, "checkCallerAllowManagedProfiles: Exception ex=" + ex);
            ok = false;
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        return ok;
    }

    /**
     * Enforce the context has android.Manifest.permission.BLUETOOTH_ADMIN permission. A
     * {@link SecurityException} would be thrown if neither the calling process or the application
+12 −12
Original line number Diff line number Diff line
@@ -685,7 +685,7 @@ public class AdapterService extends Service {

        public String getAddress() {
            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
                (!Utils.checkCaller())) {
                (!Utils.checkCallerAllowManagedProfiles(mService))) {
                Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user");
                return null;
            }
@@ -730,7 +730,7 @@ public class AdapterService extends Service {
        }

        public int getScanMode() {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getScanMode() - Not allowed for non-active user");
                return BluetoothAdapter.SCAN_MODE_NONE;
            }
@@ -795,7 +795,7 @@ public class AdapterService extends Service {
            return service.cancelDiscovery();
        }
        public boolean isDiscovering() {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "isDiscovering() - Not allowed for non-active user");
                return false;
            }
@@ -820,7 +820,7 @@ public class AdapterService extends Service {
        }

        public int getProfileConnectionState(int profile) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user");
                return BluetoothProfile.STATE_DISCONNECTED;
            }
@@ -879,7 +879,7 @@ public class AdapterService extends Service {
        }

        public String getRemoteName(BluetoothDevice device) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getRemoteName() - Not allowed for non-active user");
                return null;
            }
@@ -890,7 +890,7 @@ public class AdapterService extends Service {
        }

        public int getRemoteType(BluetoothDevice device) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getRemoteType() - Not allowed for non-active user");
                return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
            }
@@ -901,7 +901,7 @@ public class AdapterService extends Service {
        }

        public String getRemoteAlias(BluetoothDevice device) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user");
                return null;
            }
@@ -923,7 +923,7 @@ public class AdapterService extends Service {
        }

        public int getRemoteClass(BluetoothDevice device) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getRemoteClass() - Not allowed for non-active user");
                return 0;
            }
@@ -934,7 +934,7 @@ public class AdapterService extends Service {
        }

        public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user");
                return new ParcelUuid[0];
            }
@@ -945,7 +945,7 @@ public class AdapterService extends Service {
        }

        public boolean fetchRemoteUuids(BluetoothDevice device) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user");
                return false;
            }
@@ -1052,7 +1052,7 @@ public class AdapterService extends Service {

        public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
                                                  ParcelUuid uuid, int port, int flag) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "connectSocket() - Not allowed for non-active user");
                return null;
            }
@@ -1064,7 +1064,7 @@ public class AdapterService extends Service {

        public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
                                                        ParcelUuid uuid, int port, int flag) {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "createSocketChannel() - Not allowed for non-active user");
                return null;
            }
+1 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ public class HeadsetService extends ProfileService {
        }

        private HeadsetService getService() {
            if (!Utils.checkCaller()) {
            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG,"Headset call not allowed for non-active user");
                return null;
            }
+7 −3
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.PowerManager;
import android.os.UserHandle;
import android.os.PowerManager.WakeLock;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
@@ -2310,7 +2311,8 @@ final class HeadsetStateMachine extends StateMachine {
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
        mService.sendBroadcastAsUser(intent, UserHandle.ALL,
                HeadsetService.BLUETOOTH_PERM);
    }

    private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) {
@@ -2323,7 +2325,8 @@ final class HeadsetStateMachine extends StateMachine {
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
        mService.sendBroadcastAsUser(intent, UserHandle.ALL,
                HeadsetService.BLUETOOTH_PERM);
        log("Audio state " + device + ": " + prevState + "->" + newState);
    }

@@ -2348,7 +2351,8 @@ final class HeadsetStateMachine extends StateMachine {
        intent.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY
            + "." + Integer.toString(companyId));

        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
        mService.sendBroadcastAsUser(intent, UserHandle.ALL,
                HeadsetService.BLUETOOTH_PERM);
    }

    private void configAudioParameters(BluetoothDevice device)