Replace Bluetooth reflection usages with impl @hide API.

Since we are targeting Android T and above, the reflection limitation
of AdvertisingSet#getOwnAddress() only works when targeting Android O
below. This change use "framework-bluetooth.impl" to access @hide APIs
in "framework-bluetooth" just like SL4A does:
https://cs.android.com/android/platform/superproject/+/master:external/sl4a/Common/Android.bp

This change also replace some constants with @SystemAPI usages.

Test: Maunal launch NearbyFastPairProviderSimulatorApp and pair with mainline FP seeker
Test: http://recall/-/cycSROwIosTzHgYDSIqPXl/fAWLYYQQMVCw0QWuefBU7v
Bug: 214015364
Ignore-AOSP-First: nearby_not_in_aosp_yet
Change-Id: Iedd22c05803e93da529936f03f911c0e647e84ec
diff --git a/nearby/tests/multidevices/clients/proguard.flags b/nearby/tests/multidevices/clients/proguard.flags
index fd494a8..11938cd 100644
--- a/nearby/tests/multidevices/clients/proguard.flags
+++ b/nearby/tests/multidevices/clients/proguard.flags
@@ -3,8 +3,8 @@
      *;
 }
 
-# Keep simulator reflection callback.
--keep class android.nearby.fastpair.provider.** {
+# Keep AdvertisingSetCallback#onOwnAddressRead callback.
+-keep class * extends android.bluetooth.le.AdvertisingSetCallback {
      *;
 }
 
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/Android.bp b/nearby/tests/multidevices/clients/test_support/fastpair_provider/Android.bp
index 920834a..e01c436 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/Android.bp
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/Android.bp
@@ -22,7 +22,16 @@
         "src/**/*.java",
         "src/**/*.kt",
     ],
-    sdk_version: "test_current",
+    sdk_version: "core_platform",
+    libs: [
+        // order matters: classes in framework-bluetooth are resolved before framework, meaning
+        // @hide APIs in framework-bluetooth are resolved before @SystemApi stubs in framework
+        "framework-bluetooth.impl",
+        "framework",
+
+        // if sdk_version="" this gets automatically included, but here we need to add manually.
+        "framework-res",
+    ],
     static_libs: [
         "NearbyFastPairProviderLiteProtos",
         "androidx.test.core",
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/Android.bp b/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/Android.bp
index 79c5007..87d352f 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/Android.bp
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/Android.bp
@@ -16,9 +16,20 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// Build and install NearbyFastPairProviderSimulatorApp to your phone:
+// m NearbyFastPairProviderSimulatorApp
+// adb root
+// adb remount && adb reboot (make first time remount work)
+//
+// adb root
+// adb remount
+// adb push ${ANDROID_PRODUCT_OUT}/system/app/NearbyFastPairProviderSimulatorApp /system/app/
+// adb reboot
 android_app {
     name: "NearbyFastPairProviderSimulatorApp",
     sdk_version: "test_current",
+    // Sign with "platform" certificate for accessing Bluetooth @SystemAPI
+    certificate: "platform",
     static_libs: ["NearbyFastPairProviderSimulatorLib"],
     optimize: {
         enabled: true,
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/proguard.flags b/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/proguard.flags
index 28680b3..0827c60 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/proguard.flags
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/proguard.flags
@@ -1,5 +1,5 @@
-# Keep simulator reflection callback.
--keep class android.nearby.fastpair.provider.** {
+# Keep AdvertisingSetCallback#onOwnAddressRead callback.
+-keep class * extends android.bluetooth.le.AdvertisingSetCallback {
      *;
 }
 
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/FastPairSimulator.java b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/FastPairSimulator.java
index 232e84b..0d5563e 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/FastPairSimulator.java
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/FastPairSimulator.java
@@ -107,8 +107,6 @@
 import com.android.server.nearby.common.bluetooth.fastpair.Ltv;
 import com.android.server.nearby.common.bluetooth.fastpair.MessageStreamHmacEncoder;
 import com.android.server.nearby.common.bluetooth.fastpair.NamingEncoder;
-import com.android.server.nearby.common.bluetooth.fastpair.Reflect;
-import com.android.server.nearby.common.bluetooth.fastpair.ReflectionException;
 
 import com.google.common.base.Ascii;
 import com.google.common.primitives.Bytes;
@@ -185,15 +183,6 @@
 
     private static final long ADVERTISING_REFRESH_DELAY_1_MIN = TimeUnit.MINUTES.toMillis(1);
 
-    /** The user will be prompted to accept or deny the incoming pairing request */
-    public static final int PAIRING_VARIANT_CONSENT = 3;
-
-    /**
-     * The user will be prompted to enter the passkey displayed on remote device. This is used for
-     * Bluetooth 2.1 pairing.
-     */
-    public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
-
     /**
      * The size of account key filter in bytes is (1.2*n + 3), n represents the size of account key,
      * see https://developers.google.com/nearby/fast-pair/spec#advertising_when_not_discoverable.
@@ -299,7 +288,7 @@
                         // the passkey later over GATT.
                         mLocalPasskey = key;
                         checkPasskey();
-                    } else if (variant == PAIRING_VARIANT_DISPLAY_PASSKEY) {
+                    } else if (variant == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {
                         if (mPasskeyEventCallback != null) {
                             mPasskeyEventCallback.onPasskeyRequested(
                                     FastPairSimulator.this::enterPassKey);
@@ -307,7 +296,7 @@
                             mLogger.log("passkeyEventCallback is not set!");
                             enterPassKey(key);
                         }
-                    } else if (variant == PAIRING_VARIANT_CONSENT) {
+                    } else if (variant == BluetoothDevice.PAIRING_VARIANT_CONSENT) {
                         setPasskeyConfirmation(true);
 
                     } else if (variant == BluetoothDevice.PAIRING_VARIANT_PIN) {
@@ -1969,14 +1958,7 @@
 
     public void enterPassKey(int passkey) {
         mLogger.log("enterPassKey called with passkey %d.", passkey);
-        try {
-            boolean result =
-                    (Boolean) Reflect.on(mPairingDevice).withMethod("setPasskey", int.class).get(
-                            passkey);
-            mLogger.log("enterPassKey called with result %b", result);
-        } catch (ReflectionException e) {
-            mLogger.log("enterPassKey meet Exception %s.", e.getMessage());
-        }
+        mPairingDevice.setPairingConfirmation(true);
     }
 
     private void checkPasskey() {
@@ -2290,19 +2272,11 @@
     }
 
     public void disconnect(BluetoothProfile profile, BluetoothDevice device) {
-        try {
-            Reflect.on(profile).withMethod("disconnect", BluetoothDevice.class).invoke(device);
-        } catch (ReflectionException e) {
-            mLogger.log(e, "Error disconnecting device=%s from profile=%s", device, profile);
-        }
+        device.disconnect();
     }
 
     public void removeBond(BluetoothDevice device) {
-        try {
-            Reflect.on(device).withMethod("removeBond").invoke();
-        } catch (ReflectionException e) {
-            mLogger.log(e, "Error removing bond for device=%s", device);
-        }
+        device.removeBond();
     }
 
     public void resetAccountKeys() {
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/OreoFastPairAdvertiser.java b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/OreoFastPairAdvertiser.java
index bb77c11..bc0cdfe 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/OreoFastPairAdvertiser.java
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/OreoFastPairAdvertiser.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.io.BaseEncoding.base16;
 
-import android.annotation.TargetApi;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.le.AdvertiseData;
 import android.bluetooth.le.AdvertiseSettings;
@@ -27,21 +26,17 @@
 import android.bluetooth.le.AdvertisingSetParameters;
 import android.bluetooth.le.BluetoothLeAdvertiser;
 import android.nearby.fastpair.provider.utils.Logger;
-import android.os.Build.VERSION_CODES;
 import android.os.ParcelUuid;
 
 import androidx.annotation.Nullable;
 
 import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService;
-import com.android.server.nearby.common.bluetooth.fastpair.Reflect;
-import com.android.server.nearby.common.bluetooth.fastpair.ReflectionException;
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 
 /** Fast Pair advertiser taking advantage of new Android Oreo advertising features. */
-@TargetApi(VERSION_CODES.O)
 public final class OreoFastPairAdvertiser implements FastPairAdvertiser {
     private static final String TAG = "OreoFastPairAdvertiser";
     private final Logger mLogger = new Logger(TAG);
@@ -63,13 +58,7 @@
                     mLogger.log("Advertising succeeded, advertising at %s dBm", txPower);
                     simulator.setIsAdvertising(true);
                     mAdvertisingSet = set;
-
-                    try {
-                        // Requires custom Android build, see callback below.
-                        Reflect.on(set).withMethod("getOwnAddress").invoke();
-                    } catch (ReflectionException e) {
-                        mLogger.log(e, "Error calling getOwnAddress for AdvertisingSet");
-                    }
+                    mAdvertisingSet.getOwnAddress();
                 } else {
                     mLogger.log(
                             new IllegalStateException(),
@@ -88,7 +77,8 @@
                 }
             }
 
-            // Called via reflection with AdvertisingSet.getOwnAddress().
+            // Callback for AdvertisingSet.getOwnAddress().
+            @Override
             public void onOwnAddressRead(
                     AdvertisingSet set, int addressType, String address) {
                 if (!address.equals(simulator.getBleAddress())) {
@@ -108,12 +98,7 @@
     public void startAdvertising(@Nullable byte[] serviceData) {
         // To be informed that BLE address is rotated, we need to polling query it asynchronously.
         if (mAdvertisingSet != null) {
-            try {
-                // Requires custom Android build, see callback: onOwnAddressRead.
-                Reflect.on(mAdvertisingSet).withMethod("getOwnAddress").invoke();
-            } catch (ReflectionException ignored) {
-                // Ignore it due to user already knows it when setting advertisingSet.
-            }
+            mAdvertisingSet.getOwnAddress();
         }
 
         if (mSimulator.isDestroyed()) {
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt
index 6a3e59e..0cc0c92 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt
@@ -26,15 +26,13 @@
 import android.content.IntentFilter
 import android.nearby.fastpair.provider.FastPairSimulator
 import android.nearby.fastpair.provider.utils.Logger
-import android.nearby.fastpair.provider.utils.Reflect
-import android.nearby.fastpair.provider.utils.ReflectionException
 import android.os.SystemClock
 import android.provider.Settings
 
 /** Controls the local Bluetooth adapter for Fast Pair testing. */
 class BluetoothController(
     private val context: Context,
-    private val listener: EventListener,
+    private val listener: EventListener
 ) : BroadcastReceiver() {
     private val mLogger = Logger(TAG)
     private val bluetoothAdapter: BluetoothAdapter =
@@ -67,23 +65,10 @@
      * ```
      */
     fun setIoCapability(ioCapabilityClassic: Int, ioCapabilityBLE: Int) {
-        try {
-            Reflect.on(bluetoothAdapter)
-                .withMethod("setIoCapability", Int::class.javaPrimitiveType)[
-                    ioCapabilityClassic]
-        } catch (e: ReflectionException) {
-            mLogger.log(e, "Error setIoCapability to %s: %s", ioCapabilityClassic)
-        }
-        try {
-            Reflect.on(bluetoothAdapter)
-                .withMethod("setLeIoCapability", Int::class.javaPrimitiveType)[
-                    ioCapabilityBLE]
-        } catch (e: ReflectionException) {
-            mLogger.log(e, "Error setLeIoCapability to %s: %s", ioCapabilityBLE)
-        }
+        bluetoothAdapter.ioCapability = ioCapabilityClassic
+        bluetoothAdapter.leIoCapability = ioCapabilityBLE
 
         // Toggling airplane mode on/off to restart Bluetooth stack and reset the BLE.
-        // Since it also increases reliability, we will do so even if ReflectionException is caught.
         try {
             Settings.Global.putInt(
                 context.contentResolver,
@@ -165,7 +150,7 @@
 
                 override fun onServiceDisconnected(profile: Int) {}
             },
-            BLUETOOTH_PROFILE_A2DP_SINK
+            BluetoothProfile.A2DP_SINK
         )
     }
 
@@ -204,7 +189,8 @@
                         else -> remoteDevice
                     }
                 mLogger.log(
-                    "ACTION_BOND_STATE_CHANGED, the bound state of the remote device (%s) change to %s.",
+                    "ACTION_BOND_STATE_CHANGED, the bound state of " +
+                            "the remote device (%s) change to %s.",
                     remoteDevice?.remoteDeviceToString(),
                     bondState.bondStateToString()
                 )
@@ -284,9 +270,6 @@
     companion object {
         private const val TAG = "BluetoothController"
 
-        /** Hidden SystemApi field in [BluetoothProfile] interface. */
-        private const val BLUETOOTH_PROFILE_A2DP_SINK = 11
-
         private const val TURN_AIRPLANE_MODE_OFF = 0
         private const val TURN_AIRPLANE_MODE_ON = 1
     }
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/utils/Reflect.java b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/utils/Reflect.java
deleted file mode 100644
index 5ae5310..0000000
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/utils/Reflect.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.nearby.fastpair.provider.utils;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Utilities for calling methods using reflection. The main benefit of using this helper is to avoid
- * complications around exception handling when calling methods reflectively. It's not safe to use
- * Java 8's multicatch on such exceptions, because the java compiler converts multicatch into
- * ReflectiveOperationException in some instances, which doesn't work on older sdk versions.
- * Instead, use these utilities and catch ReflectionException.
- *
- * <p>Example usage:
- *
- * <pre>{@code
- * try {
- *   Reflect.on(btAdapter)
- *       .withMethod("setScanMode", int.class)
- *       .invoke(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)
- * } catch (ReflectionException e) { }
- * }</pre>
- */
-public final class Reflect {
-    private final Object mTargetObject;
-
-    private Reflect(Object targetObject) {
-        this.mTargetObject = targetObject;
-    }
-
-    /** Creates an instance of this helper to invoke methods on the given target object. */
-    public static Reflect on(Object targetObject) {
-        return new Reflect(targetObject);
-    }
-
-    /** Finds a method with the given name and parameter types. */
-    public ReflectionMethod withMethod(String methodName, Class<?>... paramTypes)
-            throws ReflectionException {
-        try {
-            return new ReflectionMethod(mTargetObject.getClass().getMethod(methodName, paramTypes));
-        } catch (NoSuchMethodException e) {
-            throw new ReflectionException(e);
-        }
-    }
-
-    /** Represents an invokable method found reflectively. */
-    public final class ReflectionMethod {
-        private final Method mMethod;
-
-        private ReflectionMethod(Method method) {
-            this.mMethod = method;
-        }
-
-        /**
-         * Invokes this instance method with the given parameters. The called method does not return
-         * a value.
-         */
-        public void invoke(Object... parameters) throws ReflectionException {
-            try {
-                mMethod.invoke(mTargetObject, parameters);
-            } catch (IllegalAccessException e) {
-                throw new ReflectionException(e);
-            } catch (InvocationTargetException e) {
-                throw new ReflectionException(e);
-            }
-        }
-
-        /**
-         * Invokes this instance method with the given parameters. The called method returns a non
-         * null
-         * value.
-         */
-        public Object get(Object... parameters) throws ReflectionException {
-            Object value;
-            try {
-                value = mMethod.invoke(mTargetObject, parameters);
-            } catch (IllegalAccessException e) {
-                throw new ReflectionException(e);
-            } catch (InvocationTargetException e) {
-                throw new ReflectionException(e);
-            }
-            if (value == null) {
-                throw new ReflectionException(new NullPointerException());
-            }
-            return value;
-        }
-    }
-}
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/utils/ReflectionException.java b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/utils/ReflectionException.java
deleted file mode 100644
index 959fd11..0000000
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/utils/ReflectionException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2022 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 android.nearby.fastpair.provider.utils;
-
-/**
- * An exception thrown during a reflection operation. Like ReflectiveOperationException, except
- * compatible on older API versions.
- */
-public final class ReflectionException extends Exception {
-    public ReflectionException(Throwable cause) {
-        super(cause.getMessage(), cause);
-    }
-}