Merge changes Ib4232854,Ic7e95cf0

* changes:
  [API] Add offloadOnly API
  [API] Upadate queryOffloadCapability API
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index 6cbed46..f3da1f0 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -262,7 +262,7 @@
 
   public class NearbyManager {
     method public static boolean isFastPairScanEnabled(@NonNull android.content.Context);
-    method public void queryOffloadScanSupport(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method public void queryOffloadCapability(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.nearby.OffloadCapability>);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void setFastPairScanEnabled(@NonNull android.content.Context, boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void startBroadcast(@NonNull android.nearby.BroadcastRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.BroadcastCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int startScan(@NonNull android.nearby.ScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.ScanCallback);
@@ -270,6 +270,23 @@
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void stopScan(@NonNull android.nearby.ScanCallback);
   }
 
+  public final class OffloadCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getVersion();
+    method public boolean isFastPairSupported();
+    method public boolean isNearbyShareSupported();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.nearby.OffloadCapability> CREATOR;
+  }
+
+  public static final class OffloadCapability.Builder {
+    ctor public OffloadCapability.Builder();
+    method @NonNull public android.nearby.OffloadCapability build();
+    method @NonNull public android.nearby.OffloadCapability.Builder setFastPairSupported(boolean);
+    method @NonNull public android.nearby.OffloadCapability.Builder setNearbyShareSupported(boolean);
+    method @NonNull public android.nearby.OffloadCapability.Builder setVersion(long);
+  }
+
   public final class PresenceBroadcastRequest extends android.nearby.BroadcastRequest implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public java.util.List<java.lang.Integer> getActions();
@@ -399,6 +416,7 @@
     method public int getScanType();
     method @NonNull public android.os.WorkSource getWorkSource();
     method public boolean isBleEnabled();
+    method public boolean isOffloadOnly();
     method public static boolean isValidScanMode(int);
     method public static boolean isValidScanType(int);
     method @NonNull public static String scanModeToString(int);
@@ -417,6 +435,7 @@
     method @NonNull public android.nearby.ScanRequest.Builder addScanFilter(@NonNull android.nearby.ScanFilter);
     method @NonNull public android.nearby.ScanRequest build();
     method @NonNull public android.nearby.ScanRequest.Builder setBleEnabled(boolean);
+    method @NonNull public android.nearby.ScanRequest.Builder setOffloadOnly(boolean);
     method @NonNull public android.nearby.ScanRequest.Builder setScanMode(int);
     method @NonNull public android.nearby.ScanRequest.Builder setScanType(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.nearby.ScanRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
diff --git a/nearby/framework/java/android/nearby/INearbyManager.aidl b/nearby/framework/java/android/nearby/INearbyManager.aidl
index 402e3a6..7af271e 100644
--- a/nearby/framework/java/android/nearby/INearbyManager.aidl
+++ b/nearby/framework/java/android/nearby/INearbyManager.aidl
@@ -39,5 +39,5 @@
 
     void stopBroadcast(in IBroadcastListener callback, String packageName, @nullable String attributionTag);
 
-    void queryOffloadScanSupport(in IOffloadCallback callback) ;
+    void queryOffloadCapability(in IOffloadCallback callback) ;
 }
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/NearbyManager.java b/nearby/framework/java/android/nearby/NearbyManager.java
index 4147c9a..b2ea044 100644
--- a/nearby/framework/java/android/nearby/NearbyManager.java
+++ b/nearby/framework/java/android/nearby/NearbyManager.java
@@ -272,16 +272,16 @@
     }
 
     /**
-     * Query if offload scan is available in a device. The query is asynchronous and
-     * result is called back in {@link Consumer}, which is set to true if offload is supported.
+     * Query offload capability in a device. The query is asynchronous and result is called back
+     * in {@link Consumer}, which is set to true if offload is supported.
      *
      * @param executor the callback will take place on this {@link Executor}
-     * @param callback the callback invoked with {@code true} if offload is supported
+     * @param callback the callback invoked with {@link OffloadCapability}
      */
-    public void queryOffloadScanSupport(@NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Boolean> callback) {
+    public void queryOffloadCapability(@NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<OffloadCapability> callback) {
         try {
-            mService.queryOffloadScanSupport(new OffloadTransport(executor, callback));
+            mService.queryOffloadCapability(new OffloadTransport(executor, callback));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -321,9 +321,9 @@
 
         private final Executor mExecutor;
         // Null when cancelled
-        volatile @Nullable Consumer<Boolean> mConsumer;
+        volatile @Nullable Consumer<OffloadCapability> mConsumer;
 
-        OffloadTransport(Executor executor, Consumer<Boolean> consumer) {
+        OffloadTransport(Executor executor, Consumer<OffloadCapability> consumer) {
             Preconditions.checkArgument(executor != null, "illegal null executor");
             Preconditions.checkArgument(consumer != null, "illegal null consumer");
             mExecutor = executor;
@@ -331,10 +331,10 @@
         }
 
         @Override
-        public void onQueryComplete(boolean isOffloadSupported) {
+        public void onQueryComplete(OffloadCapability capability) {
             mExecutor.execute(() -> {
                 if (mConsumer != null) {
-                    mConsumer.accept(isOffloadSupported);
+                    mConsumer.accept(capability);
                 }
             });
         }
diff --git a/nearby/framework/java/android/nearby/OffloadCapability.aidl b/nearby/framework/java/android/nearby/OffloadCapability.aidl
new file mode 100644
index 0000000..fe1c45e
--- /dev/null
+++ b/nearby/framework/java/android/nearby/OffloadCapability.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023, 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;
+
+/**
+ * A class that can describe what offload functions are available.
+ *
+ * {@hide}
+ */
+parcelable OffloadCapability;
+
diff --git a/nearby/framework/java/android/nearby/OffloadCapability.java b/nearby/framework/java/android/nearby/OffloadCapability.java
new file mode 100644
index 0000000..9071c1c
--- /dev/null
+++ b/nearby/framework/java/android/nearby/OffloadCapability.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2023 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;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A class that can describe what offload functions are available.
+ *
+ * @hide
+ */
+@SystemApi
+public final class OffloadCapability implements Parcelable {
+    private final boolean mFastPairSupported;
+    private final boolean mNearbyShareSupported;
+    private final long mVersion;
+
+    public boolean isFastPairSupported() {
+        return mFastPairSupported;
+    }
+
+    public boolean isNearbyShareSupported() {
+        return mNearbyShareSupported;
+    }
+
+    public long getVersion() {
+        return mVersion;
+    }
+
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBoolean(mFastPairSupported);
+        dest.writeBoolean(mNearbyShareSupported);
+        dest.writeLong(mVersion);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Creator<OffloadCapability> CREATOR = new Creator<OffloadCapability>() {
+        @Override
+        public OffloadCapability createFromParcel(Parcel in) {
+            boolean isFastPairSupported = in.readBoolean();
+            boolean isNearbyShareSupported = in.readBoolean();
+            long version = in.readLong();
+            return new Builder()
+                    .setFastPairSupported(isFastPairSupported)
+                    .setNearbyShareSupported(isNearbyShareSupported)
+                    .setVersion(version)
+                    .build();
+        }
+
+        @Override
+        public OffloadCapability[] newArray(int size) {
+            return new OffloadCapability[size];
+        }
+    };
+
+    private OffloadCapability(boolean fastPairSupported, boolean nearbyShareSupported,
+            long version) {
+        mFastPairSupported = fastPairSupported;
+        mNearbyShareSupported = nearbyShareSupported;
+        mVersion = version;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof OffloadCapability)) return false;
+        OffloadCapability that = (OffloadCapability) o;
+        return isFastPairSupported() == that.isFastPairSupported()
+                && isNearbyShareSupported() == that.isNearbyShareSupported()
+                && getVersion() == that.getVersion();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(isFastPairSupported(), isNearbyShareSupported(), getVersion());
+    }
+
+    @Override
+    public String toString() {
+        return "OffloadCapability{"
+                + "fastPairSupported=" + mFastPairSupported
+                + ", nearbyShareSupported=" + mNearbyShareSupported
+                + ", version=" + mVersion
+                + '}';
+    }
+
+    /**
+     * Builder class for {@link OffloadCapability}.
+     */
+    public static final class Builder {
+        private boolean mFastPairSupported;
+        private boolean mNearbyShareSupported;
+        private long mVersion;
+
+        /**
+         * Sets if the Nearby Share feature is supported
+         *
+         * @param fastPairSupported {@code true} if the Fast Pair feature is supported
+         */
+        @NonNull
+        public Builder setFastPairSupported(boolean fastPairSupported) {
+            mFastPairSupported = fastPairSupported;
+            return this;
+        }
+
+        /**
+         * Sets if the Nearby Share feature is supported.
+         *
+         * @param nearbyShareSupported {@code true} if the Nearby Share feature is supported
+         */
+        @NonNull
+        public Builder setNearbyShareSupported(boolean nearbyShareSupported) {
+            mNearbyShareSupported = nearbyShareSupported;
+            return this;
+        }
+
+        /**
+         * Sets the version number of Nearby Offload.
+         *
+         * @param version Nearby Offload version number
+         */
+        @NonNull
+        public Builder setVersion(long version) {
+            mVersion = version;
+            return this;
+        }
+
+        /**
+         * Builds an OffloadCapability object.
+         */
+        @NonNull
+        public OffloadCapability build() {
+            return new OffloadCapability(mFastPairSupported, mNearbyShareSupported, mVersion);
+        }
+    }
+}
diff --git a/nearby/framework/java/android/nearby/ScanRequest.java b/nearby/framework/java/android/nearby/ScanRequest.java
index 9421820..9153631 100644
--- a/nearby/framework/java/android/nearby/ScanRequest.java
+++ b/nearby/framework/java/android/nearby/ScanRequest.java
@@ -33,6 +33,8 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * An encapsulation of various parameters for requesting nearby scans.
@@ -78,6 +80,7 @@
                     .setScanType(in.readInt())
                     .setScanMode(in.readInt())
                     .setBleEnabled(in.readBoolean())
+                    .setOffloadOnly(in.readBoolean())
                     .setWorkSource(in.readTypedObject(WorkSource.CREATOR));
             final int size = in.readInt();
             for (int i = 0; i < size; i++) {
@@ -95,14 +98,16 @@
     private final @ScanType int mScanType;
     private final @ScanMode int mScanMode;
     private final boolean mBleEnabled;
+    private final boolean mOffloadOnly;
     private final @NonNull WorkSource mWorkSource;
     private final List<ScanFilter> mScanFilters;
 
     private ScanRequest(@ScanType int scanType, @ScanMode int scanMode, boolean bleEnabled,
-            @NonNull WorkSource workSource, List<ScanFilter> scanFilters) {
+            boolean offloadOnly, @NonNull WorkSource workSource, List<ScanFilter> scanFilters) {
         mScanType = scanType;
         mScanMode = scanMode;
         mBleEnabled = bleEnabled;
+        mOffloadOnly = offloadOnly;
         mWorkSource = workSource;
         mScanFilters = scanFilters;
     }
@@ -168,6 +173,13 @@
     }
 
     /**
+     * Returns if CHRE enabled for scanning.
+     */
+    public boolean isOffloadOnly() {
+        return mOffloadOnly;
+    }
+
+    /**
      * Returns Scan Filters for this request.
      */
     @NonNull
@@ -203,7 +215,8 @@
         stringBuilder.append("Request[")
                 .append("scanType=").append(mScanType);
         stringBuilder.append(", scanMode=").append(scanModeToString(mScanMode));
-        stringBuilder.append(", enableBle=").append(mBleEnabled);
+        stringBuilder.append(", bleEnabled=").append(mBleEnabled);
+        stringBuilder.append(", offloadOnly=").append(mOffloadOnly);
         stringBuilder.append(", workSource=").append(mWorkSource);
         stringBuilder.append(", scanFilters=").append(mScanFilters);
         stringBuilder.append("]");
@@ -215,6 +228,7 @@
         dest.writeInt(mScanType);
         dest.writeInt(mScanMode);
         dest.writeBoolean(mBleEnabled);
+        dest.writeBoolean(mOffloadOnly);
         dest.writeTypedObject(mWorkSource, /* parcelableFlags= */0);
         final int size = mScanFilters.size();
         dest.writeInt(size);
@@ -230,6 +244,7 @@
             return mScanType == otherRequest.mScanType
                     && (mScanMode == otherRequest.mScanMode)
                     && (mBleEnabled == otherRequest.mBleEnabled)
+                    && (mOffloadOnly == otherRequest.mOffloadOnly)
                     && (Objects.equals(mWorkSource, otherRequest.mWorkSource));
         }
         return false;
@@ -237,7 +252,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mScanType, mScanMode, mBleEnabled, mWorkSource);
+        return Objects.hash(mScanType, mScanMode, mBleEnabled, mOffloadOnly, mWorkSource);
     }
 
     /** @hide **/
@@ -260,6 +275,7 @@
         private @ScanMode int mScanMode;
 
         private boolean mBleEnabled;
+        private boolean mOffloadOnly;
         private WorkSource mWorkSource;
         private List<ScanFilter> mScanFilters;
 
@@ -267,6 +283,7 @@
         public Builder() {
             mScanType = INVALID_SCAN_TYPE;
             mBleEnabled = true;
+            mOffloadOnly = true;
             mWorkSource = new WorkSource();
             mScanFilters = new ArrayList<>();
         }
@@ -307,6 +324,22 @@
         }
 
         /**
+         * By default, a scan request can be served by either offload or
+         * non-offload implementation, depending on the resource available in the device.
+         *
+         * A client can explicitly request a scan to be served by offload only.
+         * Before the request, the client should query the offload capability by
+         * using {@link NearbyManager#queryOffloadCapability(Executor, Consumer)}}. Otherwise,
+         * {@link ScanCallback#ERROR_UNSUPPORTED} will be returned on devices without
+         * offload capability.
+         */
+        @NonNull
+        public Builder setOffloadOnly(boolean offloadOnly) {
+            mOffloadOnly = offloadOnly;
+            return this;
+        }
+
+        /**
          * Sets the work source to use for power attribution for this scan request. Defaults to
          * empty work source, which implies the caller that sends the scan request will be used
          * for power attribution.
@@ -361,7 +394,8 @@
             Preconditions.checkState(isValidScanMode(mScanMode),
                     "invalid scan mode : " + mScanMode
                             + ", scan mode must be one of ScanMode#SCAN_MODE_");
-            return new ScanRequest(mScanType, mScanMode, mBleEnabled, mWorkSource, mScanFilters);
+            return new ScanRequest(
+                    mScanType, mScanMode, mBleEnabled, mOffloadOnly, mWorkSource, mScanFilters);
         }
     }
 }
diff --git a/nearby/framework/java/android/nearby/aidl/IOffloadCallback.aidl b/nearby/framework/java/android/nearby/aidl/IOffloadCallback.aidl
index f353aff..8bef817 100644
--- a/nearby/framework/java/android/nearby/aidl/IOffloadCallback.aidl
+++ b/nearby/framework/java/android/nearby/aidl/IOffloadCallback.aidl
@@ -16,7 +16,7 @@
 
 package android.nearby.aidl;
 
-import android.nearby.NearbyDeviceParcelable;
+import android.nearby.OffloadCapability;
 
 /**
  * Listener for offload queries.
@@ -25,5 +25,5 @@
  */
 oneway interface IOffloadCallback {
         /** Invokes when ContextHub transaction completes. */
-        void onQueryComplete(boolean isOffloadSupported);
+        void onQueryComplete(in OffloadCapability capability);
 }
diff --git a/nearby/service/java/com/android/server/nearby/NearbyService.java b/nearby/service/java/com/android/server/nearby/NearbyService.java
index b70930a..202b747 100644
--- a/nearby/service/java/com/android/server/nearby/NearbyService.java
+++ b/nearby/service/java/com/android/server/nearby/NearbyService.java
@@ -147,7 +147,7 @@
     }
 
     @Override
-    public void queryOffloadScanSupport(IOffloadCallback callback) {
+    public void queryOffloadCapability(IOffloadCallback callback) {
 
     }
 
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java
index f733266..90a721e 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java
@@ -35,6 +35,7 @@
 import android.nearby.BroadcastRequest;
 import android.nearby.NearbyDevice;
 import android.nearby.NearbyManager;
+import android.nearby.OffloadCapability;
 import android.nearby.PresenceBroadcastRequest;
 import android.nearby.PrivateCredential;
 import android.nearby.ScanCallback;
@@ -177,7 +178,7 @@
     @SdkSuppress(minSdkVersion = 34, codeName = "U")
     public void queryOffloadScanSupport() {
         OffloadCallback callback = new OffloadCallback();
-        mNearbyManager.queryOffloadScanSupport(EXECUTOR, callback);
+        mNearbyManager.queryOffloadCapability(EXECUTOR, callback);
     }
 
     private void enableBluetooth() {
@@ -188,9 +189,9 @@
         }
     }
 
-    private class OffloadCallback implements Consumer<Boolean> {
+    private static class OffloadCallback implements Consumer<OffloadCapability> {
         @Override
-        public void accept(Boolean aBoolean) {
+        public void accept(OffloadCapability aBoolean) {
             // no-op for now
         }
     }
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
index de4b1c3..2201f18 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
@@ -30,7 +30,6 @@
 import android.nearby.PublicCredential;
 import android.nearby.ScanRequest;
 import android.os.Build;
-import android.os.WorkSource;
 
 import androidx.annotation.RequiresApi;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -43,12 +42,10 @@
 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
 public class ScanRequestTest {
 
-    private static final int UID = 1001;
-    private static final String APP_NAME = "android.nearby.tests";
     private static final int RSSI = -40;
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testScanType() {
         ScanRequest request = new ScanRequest.Builder()
                 .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
@@ -59,13 +56,13 @@
 
     // Valid scan type must be set to one of ScanRequest#SCAN_TYPE_
     @Test(expected = IllegalStateException.class)
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testScanType_notSet_throwsException() {
         new ScanRequest.Builder().setScanMode(SCAN_MODE_BALANCED).build();
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testScanMode_defaultLowPower() {
         ScanRequest request = new ScanRequest.Builder()
                 .setScanType(SCAN_TYPE_FAST_PAIR)
@@ -76,7 +73,7 @@
 
     /** Verify setting work source with null value in the scan request is allowed */
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testSetWorkSource_nullValue() {
         ScanRequest request = new ScanRequest.Builder()
                 .setScanType(SCAN_TYPE_FAST_PAIR)
@@ -87,38 +84,8 @@
         assertThat(request.getWorkSource().isEmpty()).isTrue();
     }
 
-    /** Verify toString returns expected string. */
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
-    public void testToString() {
-        WorkSource workSource = getWorkSource();
-        ScanRequest request = new ScanRequest.Builder()
-                .setScanType(SCAN_TYPE_FAST_PAIR)
-                .setScanMode(SCAN_MODE_BALANCED)
-                .setBleEnabled(true)
-                .setWorkSource(workSource)
-                .build();
-
-        assertThat(request.toString()).isEqualTo(
-                "Request[scanType=1, scanMode=SCAN_MODE_BALANCED, "
-                        + "enableBle=true, workSource=WorkSource{" + UID + " " + APP_NAME
-                        + "}, scanFilters=[]]");
-    }
-
-    /** Verify toString works correctly with null WorkSource. */
-    @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
-    public void testToString_nullWorkSource() {
-        ScanRequest request = new ScanRequest.Builder().setScanType(
-                SCAN_TYPE_FAST_PAIR).setWorkSource(null).build();
-
-        assertThat(request.toString()).isEqualTo("Request[scanType=1, "
-                + "scanMode=SCAN_MODE_LOW_POWER, enableBle=true, workSource=WorkSource{}, "
-                + "scanFilters=[]]");
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testisEnableBle_defaultTrue() {
         ScanRequest request = new ScanRequest.Builder()
                 .setScanType(SCAN_TYPE_FAST_PAIR)
@@ -128,7 +95,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void test_isValidScanType() {
         assertThat(ScanRequest.isValidScanType(SCAN_TYPE_FAST_PAIR)).isTrue();
         assertThat(ScanRequest.isValidScanType(SCAN_TYPE_NEARBY_PRESENCE)).isTrue();
@@ -138,7 +105,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void test_isValidScanMode() {
         assertThat(ScanRequest.isValidScanMode(SCAN_MODE_LOW_LATENCY)).isTrue();
         assertThat(ScanRequest.isValidScanMode(SCAN_MODE_BALANCED)).isTrue();
@@ -150,7 +117,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void test_scanModeToString() {
         assertThat(ScanRequest.scanModeToString(2)).isEqualTo("SCAN_MODE_LOW_LATENCY");
         assertThat(ScanRequest.scanModeToString(1)).isEqualTo("SCAN_MODE_BALANCED");
@@ -162,7 +129,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testScanFilter() {
         ScanRequest request = new ScanRequest.Builder().setScanType(
                 SCAN_TYPE_NEARBY_PRESENCE).addScanFilter(getPresenceScanFilter()).build();
@@ -172,7 +139,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void describeContents() {
         ScanRequest request = new ScanRequest.Builder()
                 .setScanType(SCAN_TYPE_FAST_PAIR)
@@ -181,7 +148,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    @SdkSuppress(minSdkVersion = 33, codeName = "T")
     public void testCreatorNewArray() {
         ScanRequest[] requests =
                 ScanRequest.CREATOR.newArray(2);
@@ -207,8 +174,4 @@
                 .addPresenceAction(action)
                 .build();
     }
-
-    private static WorkSource getWorkSource() {
-        return new WorkSource(UID, APP_NAME);
-    }
 }
diff --git a/nearby/tests/unit/src/android/nearby/ScanRequestTest.java b/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
index 12de30e..4de4282 100644
--- a/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
+++ b/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
@@ -24,11 +24,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.os.Build;
 import android.os.Parcel;
 import android.os.WorkSource;
 import android.platform.test.annotations.Presubmit;
 
+import androidx.annotation.RequiresApi;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
@@ -38,14 +41,15 @@
 @Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
 public class ScanRequestTest {
 
     private static final int RSSI = -40;
+    private static final int UID = 1001;
+    private static final String APP_NAME = "android.nearby.tests";
 
     private static WorkSource getWorkSource() {
-        final int uid = 1001;
-        final String appName = "android.nearby.tests";
-        return new WorkSource(uid, appName);
+        return new WorkSource(UID, APP_NAME);
     }
 
     /** Test creating a scan request. */
@@ -104,6 +108,7 @@
 
     /** Verify toString returns expected string. */
     @Test
+    @SdkSuppress(minSdkVersion = 34)
     public void testToString() {
         WorkSource workSource = getWorkSource();
         ScanRequest request = new ScanRequest.Builder()
@@ -115,28 +120,28 @@
 
         assertThat(request.toString()).isEqualTo(
                 "Request[scanType=1, scanMode=SCAN_MODE_BALANCED, "
-                        + "enableBle=true, workSource=WorkSource{1001 android.nearby.tests}, "
-                        + "scanFilters=[]]");
+                        + "bleEnabled=true, offloadOnly=true, "
+                        + "workSource=WorkSource{" + UID + " " + APP_NAME + "}, scanFilters=[]]");
     }
 
     /** Verify toString works correctly with null WorkSource. */
     @Test
+    @SdkSuppress(minSdkVersion = 34)
     public void testToString_nullWorkSource() {
         ScanRequest request = new ScanRequest.Builder().setScanType(
                 SCAN_TYPE_FAST_PAIR).setWorkSource(null).build();
 
         assertThat(request.toString()).isEqualTo("Request[scanType=1, "
-                + "scanMode=SCAN_MODE_LOW_POWER, enableBle=true, workSource=WorkSource{}, "
-                + "scanFilters=[]]");
+                + "scanMode=SCAN_MODE_LOW_POWER, bleEnabled=true, offloadOnly=true, "
+                + "workSource=WorkSource{}, scanFilters=[]]");
     }
 
     /** Verify writing and reading from parcel for scan request. */
     @Test
     public void testParceling() {
-        final int scanType = SCAN_TYPE_NEARBY_PRESENCE;
         WorkSource workSource = getWorkSource();
         ScanRequest originalRequest = new ScanRequest.Builder()
-                .setScanType(scanType)
+                .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
                 .setScanMode(SCAN_MODE_BALANCED)
                 .setBleEnabled(true)
                 .setWorkSource(workSource)