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

Commit 2b288b84 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Long-tail of AttributionSource plumbing." into sc-dev

parents ff62b086 7d76a0a2
Loading
Loading
Loading
Loading
+68 −21
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.bluetooth.BluetoothAdapter;
@@ -53,12 +54,15 @@ import android.os.Bundle;
import android.os.ParcelUuid;
import android.os.PowerExemptionManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Telephony;
import android.util.Log;

import com.android.bluetooth.btservice.ProfileService;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

@@ -406,6 +410,20 @@ public final class Utils {
                "Need DUMP permission");
    }

    public static AttributionSource getCallingAttributionSource() {
        int callingUid = Binder.getCallingUid();
        if (callingUid == android.os.Process.ROOT_UID) {
            callingUid = android.os.Process.SYSTEM_UID;
        }
        try {
            return new AttributionSource(callingUid,
                    AppGlobals.getPackageManager().getPackagesForUid(callingUid)[0], null);
        } catch (RemoteException e) {
            throw new IllegalStateException("Failed to resolve AttributionSource", e);
        }
    }

    @SuppressLint("AndroidFrameworkRequiresPermission")
    private static boolean checkPermissionForPreflight(Context context, String permission) {
        final int result = PermissionChecker.checkCallingOrSelfPermissionForPreflight(
                context, permission);
@@ -422,6 +440,7 @@ public final class Utils {
        }
    }

    @SuppressLint("AndroidFrameworkRequiresPermission")
    private static boolean checkPermissionForDataDelivery(Context context, String permission,
            AttributionSource attributionSource, String message) {
        final int result = PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
@@ -448,6 +467,7 @@ public final class Utils {
     *
     * <p>Should be used in situations where the app op should not be noted.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public static boolean checkConnectPermissionForPreflight(Context context) {
        return checkPermissionForPreflight(context, BLUETOOTH_CONNECT);
@@ -461,6 +481,7 @@ public final class Utils {
     * <p>Should be used in situations where data will be delivered and hence the app op should
     * be noted.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public static boolean checkConnectPermissionForDataDelivery(
            Context context, AttributionSource attributionSource, String message) {
@@ -474,6 +495,7 @@ public final class Utils {
     *
     * <p>Should be used in situations where the app op should not be noted.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
    public static boolean checkScanPermissionForPreflight(Context context) {
        return checkPermissionForPreflight(context, BLUETOOTH_SCAN);
@@ -486,6 +508,7 @@ public final class Utils {
     * <p>Should be used in situations where data will be delivered and hence the app op should
     * be noted.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
    public static boolean checkScanPermissionForDataDelivery(
            Context context, AttributionSource attributionSource, String message) {
@@ -500,6 +523,7 @@ public final class Utils {
     * <p>
     * Should be used in situations where the app op should not be noted.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
    public static boolean checkAdvertisePermissionForPreflight(Context context) {
        return checkPermissionForPreflight(context, BLUETOOTH_ADVERTISE);
@@ -513,6 +537,7 @@ public final class Utils {
     * Should be used in situations where data will be delivered and hence the
     * app op should be noted.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
    public static boolean checkAdvertisePermissionForDataDelivery(
            Context context, AttributionSource attributionSource, String message) {
@@ -553,23 +578,7 @@ public final class Utils {
        return false;
    }

    public static boolean callerIsSystemOrActiveUser(String tag, String method) {
        if (!checkCaller()) {
          Log.w(TAG, method + "() - Not allowed for non-active user and non-system user");
          return false;
        }
        return true;
    }

    public static boolean callerIsSystemOrActiveOrManagedUser(Context context, String tag, String method) {
        if (!checkCallerAllowManagedProfiles(context)) {
          Log.w(TAG, method + "() - Not allowed for non-active user and non-system and non-managed user");
          return false;
        }
        return true;
    }

    public static boolean checkCaller() {
    public static boolean checkCallerIsSystemOrActiveUser() {
        int callingUser = UserHandle.getCallingUserId();
        int callingUid = Binder.getCallingUid();
        return (sForegroundUserId == callingUser)
@@ -577,9 +586,21 @@ public final class Utils {
                || (UserHandle.getAppId(Process.SYSTEM_UID) == UserHandle.getAppId(callingUid));
    }

    public static boolean checkCallerAllowManagedProfiles(Context mContext) {
        if (mContext == null) {
            return checkCaller();
    public static boolean checkCallerIsSystemOrActiveUser(String tag) {
        final boolean res = checkCallerIsSystemOrActiveUser();
        if (!res) {
            Log.w(TAG, tag + " - Not allowed for non-active user and non-system user");
        }
        return res;
    }

    public static boolean callerIsSystemOrActiveUser(String tag, String method) {
        return checkCallerIsSystemOrActiveUser(tag + "." + method + "()");
    }

    public static boolean checkCallerIsSystemOrActiveOrManagedUser(Context context) {
        if (context == null) {
            return checkCallerIsSystemOrActiveUser();
        }
        int callingUser = UserHandle.getCallingUserId();
        int callingUid = Binder.getCallingUid();
@@ -587,7 +608,7 @@ public final class Utils {
        // Use the Bluetooth process identity when making call to get parent user
        long ident = Binder.clearCallingIdentity();
        try {
            UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
            UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
            UserInfo ui = um.getProfileParent(callingUser);
            int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;

@@ -603,6 +624,32 @@ public final class Utils {
        }
    }

    public static boolean checkCallerIsSystemOrActiveOrManagedUser(Context context, String tag) {
        final boolean res = checkCallerIsSystemOrActiveOrManagedUser(context);
        if (!res) {
            Log.w(TAG, tag + " - Not allowed for"
                    + " non-active user and non-system and non-managed user");
        }
        return res;
    }

    public static boolean callerIsSystemOrActiveOrManagedUser(Context context, String tag,
            String method) {
        return checkCallerIsSystemOrActiveOrManagedUser(context, tag + "." + method + "()");
    }

    public static boolean checkServiceAvailable(ProfileService service, String tag) {
        if (service == null) {
            Log.w(TAG, tag + " - Not present");
            return false;
        }
        if (!service.isAvailable()) {
            Log.w(TAG, tag + " - Not available");
            return false;
        }
        return true;
    }

    /**
     * Checks whether location is off and must be on for us to perform some operation
     */
+0 −1
Original line number Diff line number Diff line
@@ -205,7 +205,6 @@ public class A2dpNativeInterface {
        sendMessageToService(event);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    private boolean isMandatoryCodecPreferred(byte[] address) {
        A2dpService service = A2dpService.getA2dpService();
        if (service != null) {
+87 −126

File changed.

Preview size limit exceeded, changes collapsed.

+0 −2
Original line number Diff line number Diff line
@@ -618,7 +618,6 @@ final class A2dpStateMachine extends StateMachine {

    // NOTE: This event is processed in any state
    @VisibleForTesting
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    void processCodecConfigEvent(BluetoothCodecStatus newCodecStatus) {
        BluetoothCodecConfig prevCodecConfig = null;
        BluetoothCodecStatus prevCodecStatus = mCodecStatus;
@@ -770,7 +769,6 @@ final class A2dpStateMachine extends StateMachine {
        return Integer.toString(state);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void dump(StringBuilder sb) {
        boolean isActive = Objects.equals(mDevice, mA2dpService.getActiveDevice());
        ProfileService.println(sb,
+29 −51
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothAudioConfig;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothA2dpSink;
import android.content.AttributionSource;
import android.media.AudioManager;
import android.util.Log;

@@ -32,7 +33,6 @@ import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -185,17 +185,15 @@ public class A2dpSinkService extends ProfileService {
            implements IProfileServiceBinder {
        private A2dpSinkService mService;

        private A2dpSinkService getService() {
            if (!Utils.checkCaller()) {
                Log.w(TAG, "A2dp call not allowed for non-active user");
        @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
        private A2dpSinkService getService(AttributionSource source) {
            if (!Utils.checkCallerIsSystemOrActiveUser(TAG)
                    || !Utils.checkServiceAvailable(mService, TAG)
                    || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) {
                return null;
            }

            if (mService != null) {
            return mService;
        }
            return null;
        }

        A2dpSinkServiceBinder(A2dpSinkService svc) {
            mService = svc;
@@ -207,8 +205,8 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public boolean connect(BluetoothDevice device) {
            A2dpSinkService service = getService();
        public boolean connect(BluetoothDevice device, AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return false;
            }
@@ -216,8 +214,8 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public boolean disconnect(BluetoothDevice device) {
            A2dpSinkService service = getService();
        public boolean disconnect(BluetoothDevice device, AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return false;
            }
@@ -225,8 +223,8 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public List<BluetoothDevice> getConnectedDevices() {
            A2dpSinkService service = getService();
        public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return new ArrayList<BluetoothDevice>(0);
            }
@@ -234,8 +232,9 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
            A2dpSinkService service = getService();
        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states,
                AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return new ArrayList<BluetoothDevice>(0);
            }
@@ -243,8 +242,8 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public int getConnectionState(BluetoothDevice device) {
            A2dpSinkService service = getService();
        public int getConnectionState(BluetoothDevice device, AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return BluetoothProfile.STATE_DISCONNECTED;
            }
@@ -252,8 +251,9 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
            A2dpSinkService service = getService();
        public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy,
                AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return false;
            }
@@ -261,8 +261,8 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public int getConnectionPolicy(BluetoothDevice device) {
            A2dpSinkService service = getService();
        public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
            }
@@ -270,8 +270,8 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public boolean isA2dpPlaying(BluetoothDevice device) {
            A2dpSinkService service = getService();
        public boolean isA2dpPlaying(BluetoothDevice device, AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return false;
            }
@@ -279,8 +279,9 @@ public class A2dpSinkService extends ProfileService {
        }

        @Override
        public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
            A2dpSinkService service = getService();
        public BluetoothAudioConfig getAudioConfig(BluetoothDevice device,
                AttributionSource source) {
            A2dpSinkService service = getService(source);
            if (service == null) {
                return null;
            }
@@ -331,11 +332,7 @@ public class A2dpSinkService extends ProfileService {
     *
     * @return true if disconnect is successful, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean disconnect(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return false;
        }
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
@@ -363,11 +360,7 @@ public class A2dpSinkService extends ProfileService {
        mDeviceStateMap.remove(stateMachine.getDevice());
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public List<BluetoothDevice> getConnectedDevices() {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return Collections.emptyList();
        }
        return getDevicesMatchingConnectionStates(new int[]{BluetoothAdapter.STATE_CONNECTED});
    }

@@ -384,12 +377,8 @@ public class A2dpSinkService extends ProfileService {
        return existingStateMachine;
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates" + Arrays.toString(states));
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return Collections.emptyList();
        }
        List<BluetoothDevice> deviceList = new ArrayList<>();
        BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
        int connectionState;
@@ -416,11 +405,7 @@ public class A2dpSinkService extends ProfileService {
     * {@link BluetoothProfile#STATE_CONNECTED} if this profile is connected, or
     * {@link BluetoothProfile#STATE_DISCONNECTING} if this profile is being disconnected
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public int getConnectionState(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return BluetoothProfile.STATE_DISCONNECTED;
        }
        A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device);
        return (stateMachine == null) ? BluetoothProfile.STATE_DISCONNECTED
                : stateMachine.getState();
@@ -441,10 +426,7 @@ public class A2dpSinkService extends ProfileService {
     * @param connectionPolicy is the connection policy to set to for this profile
     * @return true if connectionPolicy is set, false on error
     */
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
        enforceCallingOrSelfPermission(
                BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission");
@@ -492,11 +474,7 @@ public class A2dpSinkService extends ProfileService {
        }
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return null;
        }
        A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device);
        // a state machine instance doesn't exist. maybe it is already gone?
        if (stateMachine == null) {
Loading