diff options
8 files changed, 124 insertions, 0 deletions
diff --git a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java index d4fc9d54e8..a4c265adf7 100644 --- a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +++ b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java @@ -306,4 +306,9 @@ public class BluetoothMethodProxy { ComponentCaller caller, Uri uri, int modeFlags) { return caller.checkContentUriPermission(uri, modeFlags); } + + /** Proxies {@link Context#grantUriPermission(String, Uri, int)}. } */ + public void grantUriPermission(Context context, String packageName, Uri uri, int modeFlags) { + context.grantUriPermission(packageName, uri, modeFlags); + } } diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java index 048c134848..73cba4e954 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java @@ -248,6 +248,12 @@ public class BluetoothOppLauncherActivity extends Activity { permittedUris, false /* isHandover */, true /* fromExternal */); + if (Flags.sendOppDevicePickerExtraIntent()) { + BluetoothOppUtility + .grantPermissionToNearbyComponent( + BluetoothOppLauncherActivity.this, + uris); + } // Done getting file info..Launch device picker // and finish this activity launchDevicePicker(); @@ -322,6 +328,11 @@ public class BluetoothOppLauncherActivity extends Activity { in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE, getPackageName()); in1.putExtra( BluetoothDevicePicker.EXTRA_LAUNCH_CLASS, BluetoothOppReceiver.class.getName()); + if (Flags.sendOppDevicePickerExtraIntent()) { + in1.putExtra( + BluetoothDevicePicker.EXTRA_DEVICE_PICKER_ORIGINAL_SEND_INTENT, + getIntent()); + } Log.v(TAG, "Launching " + BluetoothDevicePicker.ACTION_LAUNCH); startActivity(in1); } @@ -555,6 +566,10 @@ public class BluetoothOppLauncherActivity extends Activity { void sendFileInfo(String mimeType, String uriString, boolean isHandover, boolean fromExternal) { BluetoothOppManager manager = BluetoothOppManager.getInstance(getApplicationContext()); try { + if (Flags.sendOppDevicePickerExtraIntent()) { + BluetoothOppUtility.grantPermissionToNearbyComponent( + this, List.of(Uri.parse(uriString))); + } manager.saveSendingFileInfo(mimeType, uriString, isHandover, fromExternal); launchDevicePicker(); finish(); diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java index d7b75bfde2..4e8892ab35 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java @@ -38,6 +38,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.content.ActivityNotFoundException; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -50,6 +51,7 @@ import android.net.Uri; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.os.SystemProperties; +import android.provider.Settings; import android.util.EventLog; import android.util.Log; @@ -77,6 +79,9 @@ import java.util.concurrent.ConcurrentHashMap; public class BluetoothOppUtility { private static final String TAG = BluetoothOppUtility.class.getSimpleName(); + // TODO(b/398120192): use API instead of a hardcode string. + private static final String NEARBY_SHARING_COMPONENT = "nearby_sharing_component"; + /** Whether the device has the "nosdcard" characteristic, or null if not-yet-known. */ private static Boolean sNoSdCard = null; @@ -572,4 +577,30 @@ public class BluetoothOppUtility { NotificationManager nm = ctx.getSystemService(NotificationManager.class); nm.cancel(BluetoothOppNotification.NOTIFICATION_ID_PROGRESS); } + + /** Grants uri read permission to nearby sharing component. */ + static void grantPermissionToNearbyComponent(Context context, List<Uri> uris) { + String packageName = getNearbyComponentPackageName(context); + if (packageName == null) { + return; + } + for (Uri uri : uris) { + BluetoothMethodProxy.getInstance() + .grantUriPermission( + context, packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } + + private static String getNearbyComponentPackageName(Context context) { + String componentString = + Settings.Secure.getString(context.getContentResolver(), NEARBY_SHARING_COMPONENT); + if (componentString == null) { + return null; + } + ComponentName componentName = ComponentName.unflattenFromString(componentString); + if (componentName == null) { + return null; + } + return componentName.getPackageName(); + } } diff --git a/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java b/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java index fd9531105b..7bb7bbfbc3 100644 --- a/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java +++ b/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java @@ -46,6 +46,7 @@ import android.net.Uri; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; +import android.provider.Settings; import android.sysprop.BluetoothProperties; import androidx.lifecycle.Lifecycle; @@ -382,6 +383,30 @@ public class BluetoothOppLauncherActivityTest { assertThat(argument.getValue().getData()).isEqualTo(Uri.EMPTY); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_SEND_OPP_DEVICE_PICKER_EXTRA_INTENT) + public void onCreate_withActionSend_grantUriPermissionToNearbyComponent() { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + String uriString = "content://test.provider/1"; + Settings.Secure.putString( + mTargetContext.getContentResolver(), + "nearby_sharing_component", + "com.example/.BComponent"); + + ActivityScenario<BluetoothOppLauncherActivity> unused = + ActivityScenario.launch(createSendIntent(uriString)); + + verify(mMethodProxy) + .grantUriPermission( + any(), + eq("com.example"), + eq(Uri.parse(uriString)), + eq(Intent.FLAG_GRANT_READ_URI_PERMISSION)); + } + @Ignore("b/263724420") @Test public void launchDevicePicker_bluetoothNotEnabled_launchEnableActivity() throws Exception { diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java index 705c91d518..cadff94862 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java @@ -44,6 +44,7 @@ import android.content.pm.ResolveInfo; import android.database.Cursor; import android.net.Uri; import android.os.ParcelFileDescriptor; +import android.provider.Settings; import androidx.test.platform.app.InstrumentationRegistry; @@ -432,4 +433,22 @@ public class BluetoothOppUtilityTest { assertWithMessage("Exception should not happen. " + e).fail(); } } + + @Test + public void grantPermissionToNearbyComponent() { + Uri originalUri = Uri.parse("content://test.provider/1"); + Settings.Secure.putString( + mContext.getContentResolver(), + "nearby_sharing_component", + "com.example/.BComponent"); + Context spiedContext = spy(new ContextWrapper(mContext)); + + BluetoothOppUtility.grantPermissionToNearbyComponent(spiedContext, List.of(originalUri)); + + verify(spiedContext) + .grantUriPermission( + eq("com.example"), + eq(originalUri), + eq(Intent.FLAG_GRANT_READ_URI_PERMISSION)); + } } diff --git a/flags/opp.aconfig b/flags/opp.aconfig index 73604961fe..6d1a13bf21 100644 --- a/flags/opp.aconfig +++ b/flags/opp.aconfig @@ -41,3 +41,20 @@ flag { } } +flag { + name: "opp_device_picker_extra_intent_apis" + is_exported: true + namespace: "bluetooth" + description: "New API to get the original intent in Bluetooth Device Picker" + bug: "395796600" +} + +flag { + name: "send_opp_device_picker_extra_intent" + namespace: "bluetooth" + description: "Send the original intent when opening Bluetooth device picker" + bug: "397852103" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index cdb9bf0670..ef922c92e1 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -369,6 +369,7 @@ package android.bluetooth { public interface BluetoothDevicePicker { field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_DEVICE_SELECTED = "android.bluetooth.devicepicker.action.DEVICE_SELECTED"; field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LAUNCH = "android.bluetooth.devicepicker.action.LAUNCH"; + field @FlaggedApi("com.android.bluetooth.flags.opp_device_picker_extra_intent_apis") public static final String EXTRA_DEVICE_PICKER_ORIGINAL_SEND_INTENT = "android.bluetooth.extra.DEVICE_PICKER_ORIGINAL_SEND_INTENT"; field public static final String EXTRA_FILTER_TYPE = "android.bluetooth.devicepicker.extra.FILTER_TYPE"; field public static final String EXTRA_LAUNCH_CLASS = "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS"; field public static final String EXTRA_LAUNCH_PACKAGE = "android.bluetooth.devicepicker.extra.LAUNCH_PACKAGE"; diff --git a/framework/java/android/bluetooth/BluetoothDevicePicker.java b/framework/java/android/bluetooth/BluetoothDevicePicker.java index ee788dae18..7e7cd6d6b7 100644 --- a/framework/java/android/bluetooth/BluetoothDevicePicker.java +++ b/framework/java/android/bluetooth/BluetoothDevicePicker.java @@ -18,6 +18,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; +import android.annotation.FlaggedApi; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -25,6 +26,8 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; +import com.android.bluetooth.flags.Flags; + /** * A helper to show a system "Device Picker" activity to the user. * @@ -64,6 +67,14 @@ public interface BluetoothDevicePicker { String EXTRA_LAUNCH_CLASS = "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS"; /** + * Extra for the original ACTION_SEND or ACTION_SEND_MULTIPLE intent that triggered the BT + * sharing. + */ + @FlaggedApi(Flags.FLAG_OPP_DEVICE_PICKER_EXTRA_INTENT_APIS) + String EXTRA_DEVICE_PICKER_ORIGINAL_SEND_INTENT = + "android.bluetooth.extra.DEVICE_PICKER_ORIGINAL_SEND_INTENT"; + + /** * Broadcast when one BT device is selected from BT device picker screen. Selected {@link * BluetoothDevice} is returned in extra data named {@link BluetoothDevice#EXTRA_DEVICE}. */ |