Loading android/app/src/com/android/bluetooth/Utils.java +86 −11 Original line number Original line Diff line number Diff line Loading @@ -286,32 +286,98 @@ public final class Utils { } } /** /** * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION and * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION and * OP_COARSE_LOCATION is allowed */ public static boolean checkCallerHasCoarseLocation(Context context, AppOpsManager appOps, String callingPackage, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); return false; } // Check coarse, but note fine if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION " + "permission to get scan results"); return false; } /** * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION and * OP_COARSE_LOCATION is allowed or android.Manifest.permission.ACCESS_FINE_LOCATION and * OP_FINE_LOCATION is allowed * OP_FINE_LOCATION is allowed */ */ public static boolean checkCallerHasLocationPermission(Context context, AppOpsManager appOps, public static boolean checkCallerHasCoarseOrFineLocation(Context context, AppOpsManager appOps, String callingPackage, UserHandle userHandle) { String callingPackage, UserHandle userHandle) { if (context.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) if (blockedByLocationOff(context, userHandle)) { != PackageManager.PERMISSION_GRANTED || !isAppOppAllowed( Log.e(TAG, "Permission denial: Location is off."); appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return false; Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION " } if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; } // Check coarse, but note fine if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION" + "permission to get scan results"); + "permission to get scan results"); return false; return false; } } /** * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION and * OP_FINE_LOCATION is allowed */ public static boolean checkCallerHasFineLocation(Context context, AppOpsManager appOps, String callingPackage, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); Log.e(TAG, "Permission denial: Location is off."); return false; return false; } } if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; return true; } } Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION " + "permission to get scan results"); return false; } /** * Returns true if the caller holds NETWORK_SETTINGS */ public static boolean checkCallerHasNetworkSettingsPermission(Context context) { return context.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS) == PackageManager.PERMISSION_GRANTED; } /** /** * Returns true if the caller holds PEERS_MAC_ADDRESS. * Returns true if the caller holds NETWORK_SETUP_WIZARD */ */ public static boolean checkCallerHasPeersMacAddressPermission(Context context) { public static boolean checkCallerHasNetworkSetupWizardPermission(Context context) { return context.checkCallingOrSelfPermission(android.Manifest.permission.PEERS_MAC_ADDRESS) return context.checkCallingOrSelfPermission( android.Manifest.permission.NETWORK_SETUP_WIZARD) == PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED; } } Loading @@ -329,6 +395,15 @@ public final class Utils { return true; return true; } } public static boolean isQApp(Context context, String pkgName) { try { return context.getPackageManager().getApplicationInfo(pkgName, 0).targetSdkVersion >= Build.VERSION_CODES.Q; } catch (PackageManager.NameNotFoundException e) { // In case of exception, assume Q app } return true; } /** /** * Return true if the specified package name is a foreground app. * Return true if the specified package name is a foreground app. * * Loading android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -923,6 +923,7 @@ class AdapterProperties { Intent intent; Intent intent; if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) { if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) { mDiscovering = false; mDiscovering = false; mService.clearDiscoveringPackages(); mDiscoveryEndMs = System.currentTimeMillis(); mDiscoveryEndMs = System.currentTimeMillis(); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM); mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM); Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +33 −2 Original line number Original line Diff line number Diff line Loading @@ -136,6 +136,8 @@ public class AdapterService extends Service { private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; private final ArrayList<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>(); static { static { classInitNative(); classInitNative(); } } Loading Loading @@ -386,6 +388,7 @@ public class AdapterService extends Service { debugLog("onCreate()"); debugLog("onCreate()"); mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper()); mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper()); mRemoteDevices.init(); mRemoteDevices.init(); clearDiscoveringPackages(); mBinder = new AdapterServiceBinder(this); mBinder = new AdapterServiceBinder(this); mAdapterProperties = new AdapterProperties(this); mAdapterProperties = new AdapterProperties(this); mAdapterStateMachine = AdapterState.make(this); mAdapterStateMachine = AdapterState.make(this); Loading Loading @@ -1905,14 +1908,42 @@ public class AdapterService extends Service { return mAdapterProperties.setDiscoverableTimeout(timeout); return mAdapterProperties.setDiscoverableTimeout(timeout); } } ArrayList<DiscoveringPackage> getDiscoveringPackages() { return mDiscoveringPackages; } void clearDiscoveringPackages() { synchronized (mDiscoveringPackages) { mDiscoveringPackages.clear(); } } boolean startDiscovery(String callingPackage) { boolean startDiscovery(String callingPackage) { UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId()); UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId()); debugLog("startDiscovery"); debugLog("startDiscovery"); enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (!Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage, callingUser)) { mAppOps.checkPackage(callingUser.getIdentifier(), callingPackage); boolean isQApp = Utils.isQApp(this, callingPackage); String permission = null; if (Utils.checkCallerHasNetworkSettingsPermission(this)) { permission = android.Manifest.permission.NETWORK_SETTINGS; } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) { permission = android.Manifest.permission.NETWORK_SETUP_WIZARD; } else if (isQApp) { if (!Utils.checkCallerHasFineLocation(this, mAppOps, callingPackage, callingUser)) { return false; } permission = android.Manifest.permission.ACCESS_FINE_LOCATION; } else { if (!Utils.checkCallerHasCoarseLocation(this, mAppOps, callingPackage, callingUser)) { return false; return false; } } permission = android.Manifest.permission.ACCESS_COARSE_LOCATION; } synchronized (mDiscoveringPackages) { mDiscoveringPackages.add(new DiscoveringPackage(callingPackage, permission)); } return startDiscoveryNative(); return startDiscoveryNative(); } } Loading android/app/src/com/android/bluetooth/btservice/DiscoveringPackage.java 0 → 100644 +35 −0 Original line number Original line Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.btservice; final class DiscoveringPackage { private String mPackageName; private String mPermission; DiscoveringPackage(String packageName, String permission) { mPackageName = packageName; mPermission = permission; } public String getPackageName() { return mPackageName; } public String getPermission() { return mPermission; } } android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +9 −3 Original line number Original line Diff line number Diff line Loading @@ -582,10 +582,16 @@ final class RemoteDevices { intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi); intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi); intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName); intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName); final ArrayList<DiscoveringPackage> packages = sAdapterService.getDiscoveringPackages(); synchronized (packages) { for (DiscoveringPackage pkg : packages) { intent.setPackage(pkg.getPackageName()); sAdapterService.sendBroadcastMultiplePermissions(intent, new String[]{ sAdapterService.sendBroadcastMultiplePermissions(intent, new String[]{ AdapterService.BLUETOOTH_PERM, android.Manifest.permission.ACCESS_COARSE_LOCATION AdapterService.BLUETOOTH_PERM, pkg.getPermission() }); }); } } } } void aclStateChangeCallback(int status, byte[] address, int newState) { void aclStateChangeCallback(int status, byte[] address, int newState) { BluetoothDevice device = getDevice(address); BluetoothDevice device = getDevice(address); Loading Loading
android/app/src/com/android/bluetooth/Utils.java +86 −11 Original line number Original line Diff line number Diff line Loading @@ -286,32 +286,98 @@ public final class Utils { } } /** /** * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION and * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION and * OP_COARSE_LOCATION is allowed */ public static boolean checkCallerHasCoarseLocation(Context context, AppOpsManager appOps, String callingPackage, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); return false; } // Check coarse, but note fine if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION " + "permission to get scan results"); return false; } /** * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION and * OP_COARSE_LOCATION is allowed or android.Manifest.permission.ACCESS_FINE_LOCATION and * OP_FINE_LOCATION is allowed * OP_FINE_LOCATION is allowed */ */ public static boolean checkCallerHasLocationPermission(Context context, AppOpsManager appOps, public static boolean checkCallerHasCoarseOrFineLocation(Context context, AppOpsManager appOps, String callingPackage, UserHandle userHandle) { String callingPackage, UserHandle userHandle) { if (context.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) if (blockedByLocationOff(context, userHandle)) { != PackageManager.PERMISSION_GRANTED || !isAppOppAllowed( Log.e(TAG, "Permission denial: Location is off."); appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return false; Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION " } if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; } // Check coarse, but note fine if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION" + "permission to get scan results"); + "permission to get scan results"); return false; return false; } } /** * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION and * OP_FINE_LOCATION is allowed */ public static boolean checkCallerHasFineLocation(Context context, AppOpsManager appOps, String callingPackage, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); Log.e(TAG, "Permission denial: Location is off."); return false; return false; } } if (context.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { return true; return true; } } Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION " + "permission to get scan results"); return false; } /** * Returns true if the caller holds NETWORK_SETTINGS */ public static boolean checkCallerHasNetworkSettingsPermission(Context context) { return context.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS) == PackageManager.PERMISSION_GRANTED; } /** /** * Returns true if the caller holds PEERS_MAC_ADDRESS. * Returns true if the caller holds NETWORK_SETUP_WIZARD */ */ public static boolean checkCallerHasPeersMacAddressPermission(Context context) { public static boolean checkCallerHasNetworkSetupWizardPermission(Context context) { return context.checkCallingOrSelfPermission(android.Manifest.permission.PEERS_MAC_ADDRESS) return context.checkCallingOrSelfPermission( android.Manifest.permission.NETWORK_SETUP_WIZARD) == PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED; } } Loading @@ -329,6 +395,15 @@ public final class Utils { return true; return true; } } public static boolean isQApp(Context context, String pkgName) { try { return context.getPackageManager().getApplicationInfo(pkgName, 0).targetSdkVersion >= Build.VERSION_CODES.Q; } catch (PackageManager.NameNotFoundException e) { // In case of exception, assume Q app } return true; } /** /** * Return true if the specified package name is a foreground app. * Return true if the specified package name is a foreground app. * * Loading
android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -923,6 +923,7 @@ class AdapterProperties { Intent intent; Intent intent; if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) { if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) { mDiscovering = false; mDiscovering = false; mService.clearDiscoveringPackages(); mDiscoveryEndMs = System.currentTimeMillis(); mDiscoveryEndMs = System.currentTimeMillis(); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM); mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM); Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +33 −2 Original line number Original line Diff line number Diff line Loading @@ -136,6 +136,8 @@ public class AdapterService extends Service { private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; private final ArrayList<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>(); static { static { classInitNative(); classInitNative(); } } Loading Loading @@ -386,6 +388,7 @@ public class AdapterService extends Service { debugLog("onCreate()"); debugLog("onCreate()"); mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper()); mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper()); mRemoteDevices.init(); mRemoteDevices.init(); clearDiscoveringPackages(); mBinder = new AdapterServiceBinder(this); mBinder = new AdapterServiceBinder(this); mAdapterProperties = new AdapterProperties(this); mAdapterProperties = new AdapterProperties(this); mAdapterStateMachine = AdapterState.make(this); mAdapterStateMachine = AdapterState.make(this); Loading Loading @@ -1905,14 +1908,42 @@ public class AdapterService extends Service { return mAdapterProperties.setDiscoverableTimeout(timeout); return mAdapterProperties.setDiscoverableTimeout(timeout); } } ArrayList<DiscoveringPackage> getDiscoveringPackages() { return mDiscoveringPackages; } void clearDiscoveringPackages() { synchronized (mDiscoveringPackages) { mDiscoveringPackages.clear(); } } boolean startDiscovery(String callingPackage) { boolean startDiscovery(String callingPackage) { UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId()); UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId()); debugLog("startDiscovery"); debugLog("startDiscovery"); enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (!Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage, callingUser)) { mAppOps.checkPackage(callingUser.getIdentifier(), callingPackage); boolean isQApp = Utils.isQApp(this, callingPackage); String permission = null; if (Utils.checkCallerHasNetworkSettingsPermission(this)) { permission = android.Manifest.permission.NETWORK_SETTINGS; } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) { permission = android.Manifest.permission.NETWORK_SETUP_WIZARD; } else if (isQApp) { if (!Utils.checkCallerHasFineLocation(this, mAppOps, callingPackage, callingUser)) { return false; } permission = android.Manifest.permission.ACCESS_FINE_LOCATION; } else { if (!Utils.checkCallerHasCoarseLocation(this, mAppOps, callingPackage, callingUser)) { return false; return false; } } permission = android.Manifest.permission.ACCESS_COARSE_LOCATION; } synchronized (mDiscoveringPackages) { mDiscoveringPackages.add(new DiscoveringPackage(callingPackage, permission)); } return startDiscoveryNative(); return startDiscoveryNative(); } } Loading
android/app/src/com/android/bluetooth/btservice/DiscoveringPackage.java 0 → 100644 +35 −0 Original line number Original line Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.btservice; final class DiscoveringPackage { private String mPackageName; private String mPermission; DiscoveringPackage(String packageName, String permission) { mPackageName = packageName; mPermission = permission; } public String getPackageName() { return mPackageName; } public String getPermission() { return mPermission; } }
android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +9 −3 Original line number Original line Diff line number Diff line Loading @@ -582,10 +582,16 @@ final class RemoteDevices { intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi); intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi); intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName); intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName); final ArrayList<DiscoveringPackage> packages = sAdapterService.getDiscoveringPackages(); synchronized (packages) { for (DiscoveringPackage pkg : packages) { intent.setPackage(pkg.getPackageName()); sAdapterService.sendBroadcastMultiplePermissions(intent, new String[]{ sAdapterService.sendBroadcastMultiplePermissions(intent, new String[]{ AdapterService.BLUETOOTH_PERM, android.Manifest.permission.ACCESS_COARSE_LOCATION AdapterService.BLUETOOTH_PERM, pkg.getPermission() }); }); } } } } void aclStateChangeCallback(int status, byte[] address, int newState) { void aclStateChangeCallback(int status, byte[] address, int newState) { BluetoothDevice device = getDevice(address); BluetoothDevice device = getDevice(address); Loading