Merge "cronet: add test for urlresponse info" am: 709d8f3062 am: cfe63e8d71
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2464391
Change-Id: I41b107bd0781ff05a82160c6f894fb86e0de49da
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Cronet/tests/cts/Android.bp b/Cronet/tests/cts/Android.bp
index bab5ac4..d969b54 100644
--- a/Cronet/tests/cts/Android.bp
+++ b/Cronet/tests/cts/Android.bp
@@ -21,7 +21,7 @@
// cronet_test_java_defaults can be used to specify a java_defaults target that
// either enables or disables Cronet tests. This is used to disable Cronet
// tests on tm-mainline-prod where the required APIs are not present.
-cronet_test_java_defaults = "CronetTestJavaDefaultsDisabled"
+cronet_test_java_defaults = "CronetTestJavaDefaultsEnabled"
// This is a placeholder comment to avoid merge conflicts
// as cronet_test_java_defaults may have different values
// depending on the branch
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 1a9dca7..67206cd 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -36,16 +36,16 @@
// different value depending on the branch.
java_defaults {
name: "ConnectivityNextEnableDefaults",
- enabled: false,
+ enabled: true,
}
apex_defaults {
name: "ConnectivityApexDefaults",
// Tethering app to include in the AOSP apex. Branches that disable the "next" targets may use
// a stable tethering app instead, but will generally override the AOSP apex to use updatable
// package names and keys, so that apex will be unused anyway.
- apps: ["Tethering"], // Replace to "Tethering" if ConnectivityNextEnableDefaults is false.
+ apps: ["TetheringNext"], // Replace to "Tethering" if ConnectivityNextEnableDefaults is false.
}
-enable_tethering_next_apex = false
+enable_tethering_next_apex = true
// This is a placeholder comment to avoid merge conflicts
// as the above target may have different "enabled" values
// depending on the branch
@@ -54,7 +54,7 @@
// enables or disables inclusion of Cronet in the Tethering apex. This is used to disable Cronet
// on tm-mainline-prod. Note: in order for Cronet APIs to work Cronet must also be enabled
// by the cronet_java_*_defaults in common/TetheringLib/Android.bp.
-cronet_in_tethering_apex_defaults = "CronetInTetheringApexDefaultsDisabled"
+cronet_in_tethering_apex_defaults = "CronetInTetheringApexDefaultsEnabled"
// This is a placeholder comment to avoid merge conflicts
// as cronet_apex_defaults may have different values
// depending on the branch
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index 7e9e868..4c677d0 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -21,8 +21,8 @@
// specify a java_defaults target that either enables or disables Cronet. This
// is used to disable Cronet on tm-mainline-prod.
// Note: they must either both be enabled or disabled.
-cronet_java_defaults = "CronetJavaDefaultsDisabled"
-cronet_java_prejarjar_defaults = "CronetJavaPrejarjarDefaultsDisabled"
+cronet_java_defaults = "CronetJavaDefaultsEnabled"
+cronet_java_prejarjar_defaults = "CronetJavaPrejarjarDefaultsEnabled"
// This is a placeholder comment to avoid merge conflicts
// as cronet_defaults may have different values
// depending on the branch
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index 87b0a64..6613ee6 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -59,12 +59,30 @@
}
public class NearbyManager {
+ method public void queryOffloadCapability(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.nearby.OffloadCapability>);
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);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void stopBroadcast(@NonNull android.nearby.BroadcastCallback);
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();
@@ -175,8 +193,14 @@
public interface ScanCallback {
method public void onDiscovered(@NonNull android.nearby.NearbyDevice);
+ method public default void onError(int);
method public void onLost(@NonNull android.nearby.NearbyDevice);
method public void onUpdated(@NonNull android.nearby.NearbyDevice);
+ field public static final int ERROR_INVALID_ARGUMENT = 2; // 0x2
+ field public static final int ERROR_PERMISSION_DENIED = 3; // 0x3
+ field public static final int ERROR_RESOURCE_EXHAUSTED = 4; // 0x4
+ field public static final int ERROR_UNKNOWN = 0; // 0x0
+ field public static final int ERROR_UNSUPPORTED = 1; // 0x1
}
public abstract class ScanFilter {
@@ -191,6 +215,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);
@@ -209,6 +234,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/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 190d698..324f565 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -675,7 +675,7 @@
/**
* Indicates that this network should be able to prioritize latency for the internet.
*
- * Starting with {@code Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, requesting this capability with
+ * Starting with {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, requesting this capability with
* {@link ConnectivityManager#requestNetwork} requires declaration in the self-certified
* network capabilities. See {@link NetworkRequest} for the self-certification documentation.
*/
@@ -684,7 +684,7 @@
/**
* Indicates that this network should be able to prioritize bandwidth for the internet.
*
- * Starting with {@code Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, requesting this capability with
+ * Starting with {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, requesting this capability with
* {@link ConnectivityManager#requestNetwork} requires declaration in the self-certified
* network capabilities. See {@link NetworkRequest} for the self-certification documentation.
*/
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index 8843fb3..6c351d0 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -123,9 +123,9 @@
* Look up the specific capability and the {@link ConnectivityManager#requestNetwork}
* method for limitations applicable to each capability.
*
- * <p>Also, starting with {@code Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, some capabilities
+ * <p>Also, starting with {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, some capabilities
* require the application to self-certify by explicitly adding the
- * {@code android.content.pm.PackageManager#PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES}
+ * {@link android.content.pm.PackageManager#PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES}
* property in the AndroidManifest.xml, which points to an XML resource file. In the
* XML resource file, the application declares what kind of network capabilities the application
* wants to have.
diff --git a/nearby/framework/Android.bp b/nearby/framework/Android.bp
index e223b54..872606b 100644
--- a/nearby/framework/Android.bp
+++ b/nearby/framework/Android.bp
@@ -51,5 +51,7 @@
static_libs: [
"modules-utils-preconditions",
],
- visibility: ["//packages/modules/Connectivity/nearby/tests:__subpackages__"],
+ visibility: [
+ "//packages/modules/Connectivity/nearby/tests:__subpackages__",
+ "//packages/modules/Connectivity/nearby/halfsheet:__subpackages__"],
}
diff --git a/nearby/framework/java/android/nearby/INearbyManager.aidl b/nearby/framework/java/android/nearby/INearbyManager.aidl
index 0291fff..7af271e 100644
--- a/nearby/framework/java/android/nearby/INearbyManager.aidl
+++ b/nearby/framework/java/android/nearby/INearbyManager.aidl
@@ -20,6 +20,7 @@
import android.nearby.IScanListener;
import android.nearby.BroadcastRequestParcelable;
import android.nearby.ScanRequest;
+import android.nearby.aidl.IOffloadCallback;
/**
* Interface for communicating with the nearby services.
@@ -37,4 +38,6 @@
in IBroadcastListener callback, String packageName, @nullable String attributionTag);
void stopBroadcast(in IBroadcastListener callback, String packageName, @nullable String attributionTag);
+
+ void queryOffloadCapability(in IOffloadCallback callback) ;
}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/IScanListener.aidl b/nearby/framework/java/android/nearby/IScanListener.aidl
index 3e3b107..80563b7 100644
--- a/nearby/framework/java/android/nearby/IScanListener.aidl
+++ b/nearby/framework/java/android/nearby/IScanListener.aidl
@@ -34,5 +34,5 @@
void onLost(in NearbyDeviceParcelable nearbyDeviceParcelable);
/** Reports when there is an error during scanning. */
- void onError();
+ void onError(in int errorCode);
}
diff --git a/nearby/framework/java/android/nearby/NearbyManager.java b/nearby/framework/java/android/nearby/NearbyManager.java
index feed71b..333ba5c 100644
--- a/nearby/framework/java/android/nearby/NearbyManager.java
+++ b/nearby/framework/java/android/nearby/NearbyManager.java
@@ -26,8 +26,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.nearby.aidl.IOffloadCallback;
import android.os.RemoteException;
-import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -37,6 +37,7 @@
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* This class provides a way to perform Nearby related operations such as scanning, broadcasting
@@ -270,29 +271,42 @@
}
/**
- * Read from {@link Settings} whether Fast Pair scan is enabled.
+ * 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 context the {@link Context} to query the setting
- * @return whether the Fast Pair is enabled
- * @hide
+ * @param executor the callback will take place on this {@link Executor}
+ * @param callback the callback invoked with {@link OffloadCapability}
*/
- public static boolean getFastPairScanEnabled(@NonNull Context context) {
- final int enabled = Settings.Secure.getInt(
- context.getContentResolver(), FAST_PAIR_SCAN_ENABLED, 0);
- return enabled != 0;
+ public void queryOffloadCapability(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<OffloadCapability> callback) {
+ try {
+ mService.queryOffloadCapability(new OffloadTransport(executor, callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
- /**
- * Write into {@link Settings} whether Fast Pair scan is enabled
- *
- * @param context the {@link Context} to set the setting
- * @param enable whether the Fast Pair scan should be enabled
- * @hide
- */
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
- public static void setFastPairScanEnabled(@NonNull Context context, boolean enable) {
- Settings.Secure.putInt(
- context.getContentResolver(), FAST_PAIR_SCAN_ENABLED, enable ? 1 : 0);
+ private static class OffloadTransport extends IOffloadCallback.Stub {
+
+ private final Executor mExecutor;
+ // Null when cancelled
+ volatile @Nullable Consumer<OffloadCapability> mConsumer;
+
+ OffloadTransport(Executor executor, Consumer<OffloadCapability> consumer) {
+ Preconditions.checkArgument(executor != null, "illegal null executor");
+ Preconditions.checkArgument(consumer != null, "illegal null consumer");
+ mExecutor = executor;
+ mConsumer = consumer;
+ }
+
+ @Override
+ public void onQueryComplete(OffloadCapability capability) {
+ mExecutor.execute(() -> {
+ if (mConsumer != null) {
+ mConsumer.accept(capability);
+ }
+ });
+ }
}
private static class ScanListenerTransport extends IScanListener.Stub {
@@ -362,10 +376,10 @@
}
@Override
- public void onError() {
+ public void onError(int errorCode) {
mExecutor.execute(() -> {
if (mScanCallback != null) {
- Log.e("NearbyManager", "onError: There is an error in scan.");
+ mScanCallback.onError(errorCode);
}
});
}
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/PresenceDevice.java b/nearby/framework/java/android/nearby/PresenceDevice.java
index 7efa5e6..b5d9ad4 100644
--- a/nearby/framework/java/android/nearby/PresenceDevice.java
+++ b/nearby/framework/java/android/nearby/PresenceDevice.java
@@ -375,7 +375,6 @@
return this;
}
-
/**
* Sets the image url of the discovered Presence device.
*
@@ -387,7 +386,6 @@
return this;
}
-
/**
* Sets discovery timestamp, the clock is based on elapsed time.
*
@@ -399,7 +397,6 @@
return this;
}
-
/**
* Adds an extended property of the discovered presence device.
*
diff --git a/nearby/framework/java/android/nearby/ScanCallback.java b/nearby/framework/java/android/nearby/ScanCallback.java
index 1b1b4bc..7b66607 100644
--- a/nearby/framework/java/android/nearby/ScanCallback.java
+++ b/nearby/framework/java/android/nearby/ScanCallback.java
@@ -16,9 +16,13 @@
package android.nearby;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Reports newly discovered devices.
* Note: The frequency of the callback is dependent on whether the caller
@@ -31,6 +35,37 @@
*/
@SystemApi
public interface ScanCallback {
+
+ /** General error code for scan. */
+ int ERROR_UNKNOWN = 0;
+
+ /**
+ * Scan failed as the request is not supported.
+ */
+ int ERROR_UNSUPPORTED = 1;
+
+ /**
+ * Invalid argument such as out-of-range, illegal format etc.
+ */
+ int ERROR_INVALID_ARGUMENT = 2;
+
+ /**
+ * Request from clients who do not have permissions.
+ */
+ int ERROR_PERMISSION_DENIED = 3;
+
+ /**
+ * Request cannot be fulfilled due to limited resource.
+ */
+ int ERROR_RESOURCE_EXHAUSTED = 4;
+
+ /** @hide **/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ERROR_UNKNOWN, ERROR_UNSUPPORTED, ERROR_INVALID_ARGUMENT, ERROR_PERMISSION_DENIED,
+ ERROR_RESOURCE_EXHAUSTED})
+ @interface ErrorCode {
+ }
+
/**
* Reports a {@link NearbyDevice} being discovered.
*
@@ -51,4 +86,11 @@
* @param device {@link NearbyDevice} that is lost.
*/
void onLost(@NonNull NearbyDevice device);
+
+ /**
+ * Notifies clients of error from the scan.
+ *
+ * @param errorCode defined by Nearby
+ */
+ default void onError(@ErrorCode int errorCode) {}
}
diff --git a/nearby/framework/java/android/nearby/ScanRequest.java b/nearby/framework/java/android/nearby/ScanRequest.java
index 9421820..c62e3e3 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 = false;
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
new file mode 100644
index 0000000..8bef817
--- /dev/null
+++ b/nearby/framework/java/android/nearby/aidl/IOffloadCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.aidl;
+
+import android.nearby.OffloadCapability;
+
+/**
+ * Listener for offload queries.
+ *
+ * {@hide}
+ */
+oneway interface IOffloadCallback {
+ /** Invokes when ContextHub transaction completes. */
+ void onQueryComplete(in OffloadCapability capability);
+}
diff --git a/nearby/halfsheet/Android.bp b/nearby/halfsheet/Android.bp
index 8011dc6..6190d45 100644
--- a/nearby/halfsheet/Android.bp
+++ b/nearby/halfsheet/Android.bp
@@ -20,6 +20,7 @@
name: "HalfSheetUX",
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
sdk_version: "module_current",
// This is included in tethering apex, which uses min SDK 30
min_sdk_version: "30",
@@ -28,7 +29,7 @@
libs: [
"framework-bluetooth",
"framework-connectivity-t.impl",
- "nearby-service-string",
+ "framework-nearby-static",
],
static_libs: [
"androidx.annotation_annotation",
diff --git a/nearby/halfsheet/res/drawable/quantum_ic_devices_other_vd_theme_24.xml b/nearby/halfsheet/res/drawable/quantum_ic_devices_other_vd_theme_24.xml
new file mode 100644
index 0000000..3dcfdee
--- /dev/null
+++ b/nearby/halfsheet/res/drawable/quantum_ic_devices_other_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3,6h18L21,4L3,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h4v-2L3,18L3,6zM13,12L9,12v1.78c-0.61,0.55 -1,1.33 -1,2.22s0.39,1.67 1,2.22L9,20h4v-1.78c0.61,-0.55 1,-1.34 1,-2.22s-0.39,-1.67 -1,-2.22L13,12zM11,17.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM22,8h-6c-0.5,0 -1,0.5 -1,1v10c0,0.5 0.5,1 1,1h6c0.5,0 1,-0.5 1,-1L23,9c0,-0.5 -0.5,-1 -1,-1zM21,18h-4v-8h4v8z"/>
+</vector>
diff --git a/nearby/halfsheet/res/layout-land/fast_pair_device_pairing_fragment.xml b/nearby/halfsheet/res/layout-land/fast_pair_device_pairing_fragment.xml
new file mode 100644
index 0000000..545f7fa
--- /dev/null
+++ b/nearby/halfsheet/res/layout-land/fast_pair_device_pairing_fragment.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ tools:ignore="RtlCompat"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/image_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="12dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp">
+
+ <TextView
+ android:id="@+id/header_subtitle"
+ android:textColor="@color/fast_pair_half_sheet_subtitle_color"
+ android:fontFamily="google-sans"
+ android:textSize="14sp"
+ android:gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent" />
+
+ <ImageView
+ android:id="@+id/pairing_pic"
+ android:layout_width="@dimen/fast_pair_half_sheet_land_image_size"
+ android:layout_height="@dimen/fast_pair_half_sheet_land_image_size"
+ android:paddingTop="18dp"
+ android:paddingBottom="18dp"
+ android:importantForAccessibility="no"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/header_subtitle" />
+
+ <TextView
+ android:id="@+id/pin_code"
+ android:textColor="@color/fast_pair_half_sheet_subtitle_color"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/fast_pair_half_sheet_land_image_size"
+ android:paddingTop="18dp"
+ android:paddingBottom="18dp"
+ android:visibility="invisible"
+ android:textSize="50sp"
+ android:letterSpacing="0.2"
+ android:fontFamily="google-sans-medium"
+ android:gravity="center"
+ android:importantForAccessibility="yes"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/header_subtitle" />
+
+ <ProgressBar
+ android:id="@+id/connect_progressbar"
+ android:layout_width="@dimen/fast_pair_half_sheet_land_image_size"
+ android:layout_height="4dp"
+ android:indeterminate="true"
+ android:indeterminateTint="@color/fast_pair_progress_color"
+ android:indeterminateTintMode="src_in"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_marginBottom="6dp"
+ app:layout_constraintTop_toBottomOf="@+id/pairing_pic"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/mid_part"
+ app:layout_constraintTop_toBottomOf="@+id/connect_progressbar"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent">
+
+ <ImageView
+ android:id="@+id/info_icon"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@null"
+ android:layout_centerInParent="true"
+ android:layout_marginEnd="10dp"
+ android:layout_toStartOf="@id/connect_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="@drawable/fast_pair_ic_info"
+ android:visibility="invisible" />
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/connect_btn"
+ android:text="@string/paring_action_connect"
+ android:layout_height="wrap_content"
+ android:layout_width="@dimen/fast_pair_half_sheet_image_size"
+ android:layout_centerInParent="true"
+ style="@style/HalfSheetButton" />
+
+ </RelativeLayout>
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/settings_btn"
+ android:text="@string/paring_action_settings"
+ android:visibility="invisible"
+ android:layout_height="wrap_content"
+ android:layout_width="@dimen/fast_pair_half_sheet_land_image_size"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/connect_progressbar"
+ style="@style/HalfSheetButton" />
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/cancel_btn"
+ android:text="@string/paring_action_done"
+ android:visibility="invisible"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/mid_part"
+ android:gravity="start|center_vertical"
+ android:paddingTop="6dp"
+ android:paddingBottom="6dp"
+ android:layout_marginBottom="10dp"
+ style="@style/HalfSheetButtonBorderless"/>
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/setup_btn"
+ android:text="@string/paring_action_launch"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/mid_part"
+ android:paddingTop="6dp"
+ android:paddingBottom="6dp"
+ android:layout_marginBottom="10dp"
+ android:visibility="invisible"
+ android:layout_height="@dimen/fast_pair_half_sheet_bottom_button_height"
+ android:layout_width="wrap_content"
+ style="@style/HalfSheetButton" />
+
+ <!--Empty place holder to prevent pairing button from being cut off by screen-->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="30dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/setup_btn"/>
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+</ScrollView>
diff --git a/nearby/halfsheet/res/layout-land/fast_pair_half_sheet.xml b/nearby/halfsheet/res/layout-land/fast_pair_half_sheet.xml
new file mode 100644
index 0000000..e993536
--- /dev/null
+++ b/nearby/halfsheet/res/layout-land/fast_pair_half_sheet.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:ignore="RtlCompat, UselessParent, MergeRootFrame"
+ android:id="@+id/background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/card"
+ android:orientation="vertical"
+ android:transitionName="card"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity= "center|bottom"
+ android:paddingLeft="12dp"
+ android:paddingRight="12dp"
+ android:background="@drawable/half_sheet_bg"
+ android:accessibilityLiveRegion="polite"
+ android:gravity="bottom">
+
+ <RelativeLayout
+ android:id="@+id/toolbar_wrapper"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp">
+
+ <ImageView
+ android:layout_marginTop="9dp"
+ android:layout_marginBottom="9dp"
+ android:id="@+id/toolbar_image"
+ android:layout_width="42dp"
+ android:layout_height="42dp"
+ android:contentDescription="@null"
+ android:layout_toStartOf="@id/toolbar_title"
+ android:layout_centerHorizontal="true"
+ android:visibility="invisible"/>
+
+ <TextView
+ android:layout_marginTop="18dp"
+ android:layout_marginBottom="18dp"
+ android:layout_centerHorizontal="true"
+ android:id="@+id/toolbar_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:fontFamily="google-sans-medium"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:textSize="24sp"
+ android:textColor="@color/fast_pair_half_sheet_text_color"
+ style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" />
+ </RelativeLayout>
+
+ <FrameLayout
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+
+ </LinearLayout>
+
+</FrameLayout>
+
diff --git a/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml b/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml
index 7fbe229..77cd1ea 100644
--- a/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml
+++ b/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml
@@ -5,7 +5,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:ignore="RtlCompat"
- android:layout_width="match_parent" android:layout_height="match_parent">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/image_view"
@@ -16,6 +17,7 @@
android:paddingEnd="12dp"
android:paddingTop="12dp"
android:paddingBottom="12dp">
+
<TextView
android:id="@+id/header_subtitle"
android:textColor="@color/fast_pair_half_sheet_subtitle_color"
@@ -73,14 +75,15 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/connect_progressbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/info_icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
app:srcCompat="@drawable/fast_pair_ic_info"
android:layout_centerInParent="true"
android:contentDescription="@null"
@@ -113,12 +116,11 @@
android:id="@+id/cancel_btn"
android:text="@string/paring_action_done"
android:visibility="invisible"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:gravity="start|center_vertical"
android:layout_marginTop="6dp"
+ android:layout_marginBottom="16dp"
style="@style/HalfSheetButtonBorderless"/>
<com.google.android.material.button.MaterialButton
diff --git a/nearby/halfsheet/res/values-af/strings.xml b/nearby/halfsheet/res/values-af/strings.xml
index 7333e63..b0f5631 100644
--- a/nearby/halfsheet/res/values-af/strings.xml
+++ b/nearby/halfsheet/res/values-af/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Begin tans opstelling …"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Stel toestel op"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Toestel is gekoppel"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Gekoppel aan “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Kon nie koppel nie"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Kan nie koppel nie"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Probeer die toestel self saambind"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Probeer om die toestel in saambindmodus te sit"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Toestelle binne bereik"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Toestelle met jou rekening"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Jou gestoorde toestel is reg"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Naby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Toestelle"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Koppel tans …"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Battery: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Klaar"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Stoor"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Koppel"</string>
diff --git a/nearby/halfsheet/res/values-am/strings.xml b/nearby/halfsheet/res/values-am/strings.xml
index da3b144..7c0aed4 100644
--- a/nearby/halfsheet/res/values-am/strings.xml
+++ b/nearby/halfsheet/res/values-am/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ማዋቀርን በመጀመር ላይ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"መሣሪያ አዋቅር"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"መሣሪያ ተገናኝቷል"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"ከ«%s» ጋር ተገናኝቷል"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"መገናኘት አልተቻለም"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"መገናኘት አልተቻለም"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"በእጅ ከመሣሪያው ጋር ለማጣመር ይሞክሩ"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"መሣሪያውን ወደ ማጣመር ሁነታ ለማስገባት ይሞክሩ"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"በቅርብ ያሉ መሣሪያዎች"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ከመለያዎ ጋር መሣሪያዎች"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"የተቀመጠው መሣሪያዎ ይገኛል"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"በአቅራቢያ"</string>
+ <string name="common_devices" msgid="2635603125608104442">"መሣሪያዎች"</string>
+ <string name="common_connecting" msgid="160531481424245303">"በማገናኘት ላይ…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ባትሪ፦ %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ተጠናቅቋል"</string>
<string name="paring_action_save" msgid="6259357442067880136">"አስቀምጥ"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"አገናኝ"</string>
diff --git a/nearby/halfsheet/res/values-ar/strings.xml b/nearby/halfsheet/res/values-ar/strings.xml
index d0bfce4..089faaa 100644
--- a/nearby/halfsheet/res/values-ar/strings.xml
+++ b/nearby/halfsheet/res/values-ar/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"جارٍ الإعداد…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"إعداد جهاز"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"تمّ إقران الجهاز"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"تم الربط بـ \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"تعذّر الربط"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"يتعذَّر الاتصال"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"جرِّب الإقران يدويًا بالجهاز."</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"جرِّب تشغيل الجهاز في وضع الإقران."</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"الأجهزة القريبة"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"الأجهزة المرتبطة بحسابك"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"جهازك المحفوظ متاح"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"مشاركة عن قرب"</string>
+ <string name="common_devices" msgid="2635603125608104442">"الأجهزة"</string>
+ <string name="common_connecting" msgid="160531481424245303">"جارٍ الاتصال…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"البطارية: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"تم"</string>
<string name="paring_action_save" msgid="6259357442067880136">"حفظ"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ربط"</string>
diff --git a/nearby/halfsheet/res/values-as/strings.xml b/nearby/halfsheet/res/values-as/strings.xml
index 8ff4946..bb9dfcc 100644
--- a/nearby/halfsheet/res/values-as/strings.xml
+++ b/nearby/halfsheet/res/values-as/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ছেটআপ আৰম্ভ কৰি থকা হৈছে…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ডিভাইচ ছেট আপ কৰক"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ডিভাইচ সংযোগ কৰা হ’ল"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s”ৰ সৈতে সংযোগ কৰা হ’ল"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"সংযোগ কৰিব পৰা নগ’ল"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"সংযোগ কৰিব পৰা নাই"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ডিভাইচটোৰ সৈতে মেনুৱেলী পেয়াৰ কৰক"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ডিভাইচক পেয়াৰ কৰা ম’ডত ৰাখি চাওক"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"সংযোগ সীমাত থকা ডিভাইচসমূহ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"আপোনাৰ একাউণ্টত সংযোগ হোৱা ডিভাইচবোৰ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"আপুনি ছেভ কৰা ডিভাইচ উপলব্ধ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"নিকটৱৰ্তী"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ডিভাইচ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"সংযোগ কৰি থকা হৈছে…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"বেটাৰী: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"হ’ল"</string>
<string name="paring_action_save" msgid="6259357442067880136">"ছেভ কৰক"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"সংযোগ কৰক"</string>
diff --git a/nearby/halfsheet/res/values-az/strings.xml b/nearby/halfsheet/res/values-az/strings.xml
index af499ef..844963b 100644
--- a/nearby/halfsheet/res/values-az/strings.xml
+++ b/nearby/halfsheet/res/values-az/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Ayarlama başladılır…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Cihazı quraşdırın"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Cihaz qoşulub"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” şəbəkəsinə qoşulub"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Qoşulmaq mümkün olmadı"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Qoşulmaq olmur"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Cihazı manual olaraq birləşdirin"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Cihazı qoşalaşdırma rejiminə qoymağa çalışın"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Əl altında olan cihazlar"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Hesabınızdakı cihazlar"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Yadda saxlanmış cihazınız əlçatandır"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Yaxınlıqda"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Cihazlar"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Qoşulur…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batareya: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Oldu"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Saxlayın"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Qoşun"</string>
diff --git a/nearby/halfsheet/res/values-b+sr+Latn/strings.xml b/nearby/halfsheet/res/values-b+sr+Latn/strings.xml
index eea6b64..fcd1dc6 100644
--- a/nearby/halfsheet/res/values-b+sr+Latn/strings.xml
+++ b/nearby/halfsheet/res/values-b+sr+Latn/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Podešavanje se pokreće…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Podesite uređaj"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Uređaj je povezan"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Povezani ste sa uređajem %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Povezivanje nije uspelo"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Povezivanje nije uspelo"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Probajte da uparite ručno sa uređajem"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Probajte da prebacite uređaj u režim uparivanja"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Uređaji u dometu"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Uređaji povezani sa nalogom"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Sačuvani uređaj je dostupan"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"U blizini"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Uređaji"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Povezuje se…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterija: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Gotovo"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Sačuvaj"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Poveži"</string>
diff --git a/nearby/halfsheet/res/values-be/strings.xml b/nearby/halfsheet/res/values-be/strings.xml
index a5c1ef6..f469922 100644
--- a/nearby/halfsheet/res/values-be/strings.xml
+++ b/nearby/halfsheet/res/values-be/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Пачынаецца наладжванне…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Наладзьце прыладу"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Прылада падключана"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Падключана да прылады \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Не ўдалося падключыцца"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Не ўдалося падключыцца"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Паспрабуйце спалучыць прыладу ўручную"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Перавядзіце прыладу ў рэжым спалучэння"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Прылады ў межах дасягальнасці"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Прылады з вашым уліковым запісам"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Ёсць захаваная вамі прылада"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Паблізу"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Прылады"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Падключэнне…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Узровень зараду: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Гатова"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Захаваць"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Падключыць"</string>
diff --git a/nearby/halfsheet/res/values-bg/strings.xml b/nearby/halfsheet/res/values-bg/strings.xml
index 0ee7aef..a0c5103 100644
--- a/nearby/halfsheet/res/values-bg/strings.xml
+++ b/nearby/halfsheet/res/values-bg/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Настройването се стартира…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Настройване на устройството"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Устройството е свързано"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Установена е връзка с(ъс) „%s“"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Свързването не бе успешно"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Не може да се установи връзка"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Опитайте да сдвоите устройството ръчно"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Опитайте да зададете режим на сдвояване за устройството"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Устройства в обхват"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Устройства с профила ви"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Запазеното ви у-во е налице"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"В близост"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Устройства"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Свързва се…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батерия: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Готово"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Запазване"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Свързване"</string>
diff --git a/nearby/halfsheet/res/values-bn/strings.xml b/nearby/halfsheet/res/values-bn/strings.xml
index 484e35b..272d285 100644
--- a/nearby/halfsheet/res/values-bn/strings.xml
+++ b/nearby/halfsheet/res/values-bn/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"সেট-আপ করা শুরু হচ্ছে…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ডিভাইস সেট-আপ করুন"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ডিভাইস কানেক্ট হয়েছে"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s”-এ কানেক্ট করা হয়েছে"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"কানেক্ট করা যায়নি"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"কানেক্ট করা যায়নি"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ডিভাইসে ম্যানুয়ালি পেয়ার করার চেষ্টা করুন"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ডিভাইস \'যোগ করার\' মোডে রাখার চেষ্টা করুন"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"কাছে রয়েছে এমন ডিভাইস"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"আপনার অ্যাকাউন্টের সাথে কানেক্ট থাকা ডিভাইস"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"আপনার সেভ করা ডিভাইস উপলভ্য আছে"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"আশেপাশে"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ডিভাইস"</string>
+ <string name="common_connecting" msgid="160531481424245303">"কানেক্ট করা হচ্ছে…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ব্যাটারি: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"হয়ে গেছে"</string>
<string name="paring_action_save" msgid="6259357442067880136">"সেভ করুন"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"কানেক্ট করুন"</string>
diff --git a/nearby/halfsheet/res/values-bs/strings.xml b/nearby/halfsheet/res/values-bs/strings.xml
index 2fc8644..47f13c3 100644
--- a/nearby/halfsheet/res/values-bs/strings.xml
+++ b/nearby/halfsheet/res/values-bs/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Pokretanje postavljanja…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Postavi uređaj"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Uređaj je povezan"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Povezano s uređajem “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Povezivanje nije uspjelo"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nije moguće povezati"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Pokušajte ručno upariti uređaj"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Pokušajte staviti uređaj u način rada za uparivanje"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Uređaji u dometu"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Uređaji s vašim računom"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Sačuvani uređaj je dostupan"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"U blizini"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Uređaji"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Povezivanje…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterija: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Gotovo"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Sačuvaj"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Poveži"</string>
diff --git a/nearby/halfsheet/res/values-ca/strings.xml b/nearby/halfsheet/res/values-ca/strings.xml
index 8912792..44ebc3e 100644
--- a/nearby/halfsheet/res/values-ca/strings.xml
+++ b/nearby/halfsheet/res/values-ca/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iniciant la configuració…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configura el dispositiu"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"El dispositiu s\'ha connectat"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connectat a %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"No s\'ha pogut connectar"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"No es pot establir la connexió"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Prova de vincular el dispositiu manualment"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prova d\'activar el mode de vinculació al dispositiu"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositius a l\'abast"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositius amb el teu compte"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Dispositiu desat disponible"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"A prop"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositius"</string>
+ <string name="common_connecting" msgid="160531481424245303">"S\'està connectant…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Fet"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Desa"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connecta"</string>
diff --git a/nearby/halfsheet/res/values-cs/strings.xml b/nearby/halfsheet/res/values-cs/strings.xml
index 7e7ea3c..53d27ab 100644
--- a/nearby/halfsheet/res/values-cs/strings.xml
+++ b/nearby/halfsheet/res/values-cs/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Zahajování nastavení…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Nastavení zařízení"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Zařízení je připojeno"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Připojeno k zařízení %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nelze se připojit"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nepodařilo se připojit"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Zkuste zařízení spárovat ručně"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Přepněte zařízení do režimu párování"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Zařízení v dosahu"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Zařízení s vaším účtem"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Je dostupné uložené zařízení"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"V okolí"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Zařízení"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Připojování…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterie: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Hotovo"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Uložit"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Připojit"</string>
diff --git a/nearby/halfsheet/res/values-da/strings.xml b/nearby/halfsheet/res/values-da/strings.xml
index 1d937e2..89b221f 100644
--- a/nearby/halfsheet/res/values-da/strings.xml
+++ b/nearby/halfsheet/res/values-da/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Begynder konfiguration…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Konfigurer enhed"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Enheden er forbundet"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Der er oprettet forbindelse til \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Forbindelsen kan ikke oprettes"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Kunne ikke forbindes"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Prøv at parre med enheden manuelt"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prøv at sætte enheden i parringstilstand"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Enheder inden for rækkevidde"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Enheder med din konto"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Din gemte enhed er tilgængelig"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Tæt på"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Enheder"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Forbinder…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batteri: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Luk"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Gem"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Opret forbindelse"</string>
diff --git a/nearby/halfsheet/res/values-de/strings.xml b/nearby/halfsheet/res/values-de/strings.xml
index 9186a44..de54114 100644
--- a/nearby/halfsheet/res/values-de/strings.xml
+++ b/nearby/halfsheet/res/values-de/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Einrichtung wird gestartet..."</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Gerät einrichten"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Gerät verbunden"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Mit „%s“ verbunden"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Verbindung nicht möglich"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Kein Verbindungsaufbau möglich"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Versuche, das Gerät manuell zu koppeln"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Versuche, das Gerät in den Kopplungsmodus zu versetzen"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Geräte in Reichweite"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Geräte mit deinem Konto"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Gespeichertes Gerät verfügbar"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Geräte"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Wird verbunden…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Akkustand: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Fertig"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Speichern"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Verbinden"</string>
diff --git a/nearby/halfsheet/res/values-el/strings.xml b/nearby/halfsheet/res/values-el/strings.xml
index 3e18a93..1ea467a 100644
--- a/nearby/halfsheet/res/values-el/strings.xml
+++ b/nearby/halfsheet/res/values-el/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Έναρξη ρύθμισης…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Ρύθμιση συσκευής"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Η συσκευή συνδέθηκε"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Συνδέθηκε με τη συσκευή %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Αδυναμία σύνδεσης"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Δεν είναι δυνατή η σύνδεση"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Δοκιμάστε να κάνετε μη αυτόματη σύζευξη στη συσκευή"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Δοκιμάστε να θέσετε τη συσκευή σε λειτουργία σύζευξης"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Συσκευές εντός εμβέλειας"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Συσκευές με τον λογαριασμό σας"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Η αποθ. συσκ. είναι διαθέσιμη"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Κοντά"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Συσκευές"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Σύνδεση…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Μπαταρία: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Τέλος"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Αποθήκευση"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Σύνδεση"</string>
diff --git a/nearby/halfsheet/res/values-en-rAU/strings.xml b/nearby/halfsheet/res/values-en-rAU/strings.xml
index d4ed675..b7039a1 100644
--- a/nearby/halfsheet/res/values-en-rAU/strings.xml
+++ b/nearby/halfsheet/res/values-en-rAU/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Starting setup…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Set up device"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Device connected"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connected to \'%s\'"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Couldn\'t connect"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Unable to connect"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Try pairing to the device manually"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Try putting the device into pairing mode"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Devices within reach"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Devices with your account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Your saved device is available"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Devices"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connecting…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Battery: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Done"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Save"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connect"</string>
diff --git a/nearby/halfsheet/res/values-en-rCA/strings.xml b/nearby/halfsheet/res/values-en-rCA/strings.xml
index 6094199..06b3a5e 100644
--- a/nearby/halfsheet/res/values-en-rCA/strings.xml
+++ b/nearby/halfsheet/res/values-en-rCA/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Starting Setup…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Set up device"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Device connected"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connected to “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Couldn\'t connect"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Unable to connect"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Try manually pairing to the device"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Try putting the device into pairing mode"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Devices within reach"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Devices with your account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Your saved device is available"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Devices"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connecting…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Battery: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Done"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Save"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connect"</string>
diff --git a/nearby/halfsheet/res/values-en-rGB/strings.xml b/nearby/halfsheet/res/values-en-rGB/strings.xml
index d4ed675..b7039a1 100644
--- a/nearby/halfsheet/res/values-en-rGB/strings.xml
+++ b/nearby/halfsheet/res/values-en-rGB/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Starting setup…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Set up device"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Device connected"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connected to \'%s\'"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Couldn\'t connect"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Unable to connect"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Try pairing to the device manually"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Try putting the device into pairing mode"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Devices within reach"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Devices with your account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Your saved device is available"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Devices"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connecting…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Battery: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Done"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Save"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connect"</string>
diff --git a/nearby/halfsheet/res/values-en-rIN/strings.xml b/nearby/halfsheet/res/values-en-rIN/strings.xml
index d4ed675..b7039a1 100644
--- a/nearby/halfsheet/res/values-en-rIN/strings.xml
+++ b/nearby/halfsheet/res/values-en-rIN/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Starting setup…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Set up device"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Device connected"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connected to \'%s\'"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Couldn\'t connect"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Unable to connect"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Try pairing to the device manually"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Try putting the device into pairing mode"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Devices within reach"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Devices with your account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Your saved device is available"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Devices"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connecting…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Battery: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Done"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Save"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connect"</string>
diff --git a/nearby/halfsheet/res/values-en-rXC/strings.xml b/nearby/halfsheet/res/values-en-rXC/strings.xml
index 460cc1b..c71272e 100644
--- a/nearby/halfsheet/res/values-en-rXC/strings.xml
+++ b/nearby/halfsheet/res/values-en-rXC/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Starting Setup…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Set up device"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Device connected"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connected to “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Couldn\'t connect"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Unable to connect"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Try manually pairing to the device"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Try putting the device into pairing mode"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Devices within reach"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Devices with your account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Your saved device is available"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Devices"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connecting…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Battery: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Done"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Save"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connect"</string>
diff --git a/nearby/halfsheet/res/values-es-rUS/strings.xml b/nearby/halfsheet/res/values-es-rUS/strings.xml
index d8fb283..05eb75d 100644
--- a/nearby/halfsheet/res/values-es-rUS/strings.xml
+++ b/nearby/halfsheet/res/values-es-rUS/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iniciando la configuración…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configuración del dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Se conectó el dispositivo"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Se estableció conexión con \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"No se pudo establecer conexión"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"No se pudo establecer conexión"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Intenta vincular el dispositivo manualmente"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prueba poner el dispositivo en el modo de vinculación"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivos al alcance"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivos con tu cuenta"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"El dispositivo está disponible"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivos"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Conectando…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batería: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Listo"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Guardar"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Conectar"</string>
diff --git a/nearby/halfsheet/res/values-es/strings.xml b/nearby/halfsheet/res/values-es/strings.xml
index 4b8340a..7142a1a 100644
--- a/nearby/halfsheet/res/values-es/strings.xml
+++ b/nearby/halfsheet/res/values-es/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iniciando configuración…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configurar el dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Dispositivo conectado"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Conectado a \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"No se ha podido conectar"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"No se ha podido conectar"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Prueba a emparejar el dispositivo manualmente"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prueba a poner el dispositivo en modo Emparejamiento"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivos al alcance"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivos conectados con tu cuenta"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Dispositivo guardado disponible"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivos"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Conectando…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batería: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Hecho"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Guardar"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Conectar"</string>
diff --git a/nearby/halfsheet/res/values-et/strings.xml b/nearby/halfsheet/res/values-et/strings.xml
index e6abc64..20a46a5 100644
--- a/nearby/halfsheet/res/values-et/strings.xml
+++ b/nearby/halfsheet/res/values-et/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Seadistuse käivitamine …"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Seadistage seade"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Seade on ühendatud"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Ühendatud seadmega „%s“"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Ühendamine ebaõnnestus"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Ühendust ei õnnestu luua"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Proovige seadmega käsitsi siduda"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Lülitage seade sidumisrežiimi"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Ühendusulatuses olevad seadmed"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Teie kontoga ühendatud seadmed"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Salvestatud seade on saadaval"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Läheduses"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Seadmed"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Ühendamine …"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Aku: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Valmis"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Salvesta"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Ühenda"</string>
diff --git a/nearby/halfsheet/res/values-eu/strings.xml b/nearby/halfsheet/res/values-eu/strings.xml
index 4243fd5..cd6eb34 100644
--- a/nearby/halfsheet/res/values-eu/strings.xml
+++ b/nearby/halfsheet/res/values-eu/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Konfigurazio-prozesua abiarazten…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Konfiguratu gailua"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Konektatu da gailua"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"%s gailura konektatuta"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Ezin izan da konektatu"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Ezin da konektatu"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Saiatu gailua eskuz parekatzen"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Jarri gailua parekatzeko moduan"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Estaldura-eremuko gailuak"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Kontura konektatutako gailuak"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Gordetako gailua erabilgarri dago"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Gailuak"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Konektatzen…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %% %d"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Eginda"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Gorde"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Konektatu"</string>
diff --git a/nearby/halfsheet/res/values-fa/strings.xml b/nearby/halfsheet/res/values-fa/strings.xml
index 3585f95..7490e0f 100644
--- a/nearby/halfsheet/res/values-fa/strings.xml
+++ b/nearby/halfsheet/res/values-fa/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"درحال شروع راهاندازی…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"راهاندازی دستگاه"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"دستگاه متصل شد"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"به «%s» متصل شد"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"متصل نشد"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"اتصال برقرار نشد"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"مرتبطسازی با دستگاه را بهصورت دستی امتحان کنید"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"دستگاه را در حالت مرتبطسازی قرار دهید"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"دستگاههای دردسترس"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"دستگاههای متصل به حسابتان"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"دستگاه ذخیرهشدهتان دردسترس است"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"اطراف"</string>
+ <string name="common_devices" msgid="2635603125608104442">"دستگاهها"</string>
+ <string name="common_connecting" msgid="160531481424245303">"درحال اتصال…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"باتری: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"تمام"</string>
<string name="paring_action_save" msgid="6259357442067880136">"ذخیره"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"متصل کردن"</string>
diff --git a/nearby/halfsheet/res/values-fi/strings.xml b/nearby/halfsheet/res/values-fi/strings.xml
index e8d47de..b488b3e 100644
--- a/nearby/halfsheet/res/values-fi/strings.xml
+++ b/nearby/halfsheet/res/values-fi/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Aloitetaan käyttöönottoa…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Määritä laite"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Laite on yhdistetty"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"%s yhdistetty"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Ei yhteyttä"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Yhdistäminen epäonnistui"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Yritä yhdistää laitteet manuaalisesti"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Kokeile asettaa laite parinmuodostustilaan"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Kantoalueella olevat laitteet"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Tiliisi liitetyt laitteet"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Laitteesi on käytettävissä"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Lähellä"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Laitteet"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Yhdistetään…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Akku: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Valmis"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Tallenna"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Yhdistä"</string>
diff --git a/nearby/halfsheet/res/values-fr-rCA/strings.xml b/nearby/halfsheet/res/values-fr-rCA/strings.xml
index 64dd107..9a48890 100644
--- a/nearby/halfsheet/res/values-fr-rCA/strings.xml
+++ b/nearby/halfsheet/res/values-fr-rCA/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Démarrage de la configuration…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configurer l\'appareil"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Appareil associé"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connecté à l\'appareil suivant : « %s »"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Impossible d\'associer"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Échec de la connexion"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Essayez d\'associer manuellement l\'appareil"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Essayez de mettre l\'appareil en mode d\'association"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Appareils à portée"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Appareils connectés à votre compte"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Appareil enregistré accessible"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"À proximité"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Appareils"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connexion en cours…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Pile : %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"OK"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Enregistrer"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Associer"</string>
diff --git a/nearby/halfsheet/res/values-fr/strings.xml b/nearby/halfsheet/res/values-fr/strings.xml
index 484c57b..f1263ab 100644
--- a/nearby/halfsheet/res/values-fr/strings.xml
+++ b/nearby/halfsheet/res/values-fr/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Début de la configuration…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configurer un appareil"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Appareil associé"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connecté à \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Impossible de se connecter"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Impossible de se connecter"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Essayez d\'associer manuellement l\'appareil"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Essayez de mettre l\'appareil en mode association"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Appareils à portée de main"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Appareils connectés à votre compte"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Appareil enregistré disponible"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"À proximité"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Appareils"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connexion…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batterie : %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"OK"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Enregistrer"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connecter"</string>
diff --git a/nearby/halfsheet/res/values-gl/strings.xml b/nearby/halfsheet/res/values-gl/strings.xml
index 30393ff..91eac4f 100644
--- a/nearby/halfsheet/res/values-gl/strings.xml
+++ b/nearby/halfsheet/res/values-gl/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iniciando configuración…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configura o dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Conectouse o dispositivo"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"O dispositivo conectouse a %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Non se puido conectar"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Non se puido conectar"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Proba a vincular o dispositivo manualmente"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Proba a poñer o dispositivo no modo de vinculación"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivos dentro do alcance"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivos conectados á túa conta"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Dispositivo gardado dispoñible"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivos"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Conectando…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batería: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Feito"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Gardar"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Conectar"</string>
diff --git a/nearby/halfsheet/res/values-gu/strings.xml b/nearby/halfsheet/res/values-gu/strings.xml
index 03b057d..a7a7a2b 100644
--- a/nearby/halfsheet/res/values-gu/strings.xml
+++ b/nearby/halfsheet/res/values-gu/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"સેટઅપ શરૂ કરી રહ્યાં છીએ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ડિવાઇસનું સેટઅપ કરો"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ડિવાઇસ કનેક્ટ કર્યું"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” સાથે કનેક્ટ કરેલું"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"કનેક્ટ કરી શક્યા નથી"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"કનેક્ટ કરી શકાયું નથી"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ડિવાઇસથી મેન્યૂઅલી જોડાણ બનાવવાનો પ્રયાસ કરો"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ડિવાઇસને જોડાણ બનાવવાના મોડમાં રાખવાનો પ્રયાસ કરો"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"પહોંચની અંદરના ડિવાઇસ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"તમારા એકાઉન્ટ સાથેના ડિવાઇસ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"તમારું સાચવેલું ડિવાઇસ ઉપલબ્ધ છે"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"શેરિંગ"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ડિવાઇસ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"કનેક્ટ કરી રહ્યાં છીએ…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"બૅટરી: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"થઈ ગયું"</string>
<string name="paring_action_save" msgid="6259357442067880136">"સાચવો"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"કનેક્ટ કરો"</string>
diff --git a/nearby/halfsheet/res/values-hi/strings.xml b/nearby/halfsheet/res/values-hi/strings.xml
index ecd420e..dff9496 100644
--- a/nearby/halfsheet/res/values-hi/strings.xml
+++ b/nearby/halfsheet/res/values-hi/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"सेट अप शुरू किया जा रहा है…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"डिवाइस सेट अप करें"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"डिवाइस कनेक्ट हो गया"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” से कनेक्ट हो गया है"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"कनेक्ट नहीं किया जा सका"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"कनेक्ट नहीं किया जा सका"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"डिवाइस को मैन्युअल तरीके से दूसरे डिवाइस से जोड़ने की कोशिश करें"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"डिवाइस को दूसरे डिवाइस से जोड़ने वाले मोड में रखें"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ऐसे डिवाइस जो रेंज में हैं"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"आपके खाते से जुड़े डिवाइस"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"सेव किया गया डिवाइस उपलब्ध है"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"आस-पास शेयरिंग"</string>
+ <string name="common_devices" msgid="2635603125608104442">"डिवाइस"</string>
+ <string name="common_connecting" msgid="160531481424245303">"कनेक्ट हो रहा है…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"बैटरी: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"हो गया"</string>
<string name="paring_action_save" msgid="6259357442067880136">"सेव करें"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"कनेक्ट करें"</string>
diff --git a/nearby/halfsheet/res/values-hr/strings.xml b/nearby/halfsheet/res/values-hr/strings.xml
index 5a3de8f..13952b8 100644
--- a/nearby/halfsheet/res/values-hr/strings.xml
+++ b/nearby/halfsheet/res/values-hr/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Pokretanje postavljanja…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Postavi uređaj"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Uređaj je povezan"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Povezano s uređajem %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Povezivanje nije uspjelo"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Povezivanje nije uspjelo"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Pokušajte ručno upariti s uređajem"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Pokušajte staviti uređaj u način uparivanja"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Uređaji u dometu"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Uređaji s vašim računom"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Spremljeni je uređaj dostupan"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"U blizini"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Uređaji"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Povezivanje…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterija: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Gotovo"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Spremi"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Poveži"</string>
diff --git a/nearby/halfsheet/res/values-hu/strings.xml b/nearby/halfsheet/res/values-hu/strings.xml
index ba3d2e0..3d810d4 100644
--- a/nearby/halfsheet/res/values-hu/strings.xml
+++ b/nearby/halfsheet/res/values-hu/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Beállítás megkezdése…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Eszköz beállítása"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Eszköz csatlakoztatva"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Csatlakoztatva a következőhöz: %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nem sikerült csatlakozni"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nem sikerült csatlakozni"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Próbálkozzon az eszköz kézi párosításával"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Próbálja meg bekapcsolni az eszközön a párosítási módot"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Elérhető eszközök"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"A fiókjával társított eszközök"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"A mentett eszköze elérhető"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Közeli"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Eszközök"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Csatlakozás…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Akkumulátor: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Kész"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Mentés"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Csatlakozás"</string>
diff --git a/nearby/halfsheet/res/values-hy/strings.xml b/nearby/halfsheet/res/values-hy/strings.xml
index ecabd16..57b9256 100644
--- a/nearby/halfsheet/res/values-hy/strings.xml
+++ b/nearby/halfsheet/res/values-hy/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Կարգավորում…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Կարգավորեք սարքը"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Սարքը զուգակցվեց"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"«%s» սարքի հետ կապը հաստատվեց"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Չհաջողվեց միանալ"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Չհաջողվեց կապ հաստատել"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Փորձեք ձեռքով զուգակցել սարքը"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Փորձեք սարքում միացնել զուգակցման ռեժիմը"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Սարքեր հասանելիության տիրույթում"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Ձեր հաշվի հետ կապված սարքեր"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Պահված սարքը հասանելի է"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Մոտակայքում"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Սարքեր"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Միացում…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Մարտկոցի լիցքը՝ %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Պատրաստ է"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Պահել"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Միանալ"</string>
diff --git a/nearby/halfsheet/res/values-in/strings.xml b/nearby/halfsheet/res/values-in/strings.xml
index dc777b2..c665572 100644
--- a/nearby/halfsheet/res/values-in/strings.xml
+++ b/nearby/halfsheet/res/values-in/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Memulai Penyiapan …"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Siapkan perangkat"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Perangkat terhubung"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Terhubung ke “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Tidak dapat terhubung"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Tidak dapat terhubung"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Coba sambungkan ke perangkat secara manual"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Coba masukkan perangkat ke dalam mode penyambungan"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Perangkat dalam jangkauan"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Perangkat dengan akun Anda"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Perangkat tersimpan tersedia"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Berbagi Langsung"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Perangkat"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Menghubungkan …"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Daya baterai: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Selesai"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Simpan"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Hubungkan"</string>
diff --git a/nearby/halfsheet/res/values-is/strings.xml b/nearby/halfsheet/res/values-is/strings.xml
index ee094d9..04a4de4 100644
--- a/nearby/halfsheet/res/values-is/strings.xml
+++ b/nearby/halfsheet/res/values-is/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Ræsir uppsetningu…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Uppsetning tækis"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Tækið er tengt"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Tengt við „%s“"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Tenging mistókst"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Tenging tókst ekki"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Prófaðu að para tækið handvirkt"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prófaðu að kveikja á pörunarstillingu í tækinu"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Nálæg tæki"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Tæki tengd reikningnum þínum"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Vistaða tækið er tiltækt"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nálægt"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Tæki"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Tengist…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Rafhlaða: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Lokið"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Vista"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Tengja"</string>
diff --git a/nearby/halfsheet/res/values-it/strings.xml b/nearby/halfsheet/res/values-it/strings.xml
index 700dd77..2ffe268 100644
--- a/nearby/halfsheet/res/values-it/strings.xml
+++ b/nearby/halfsheet/res/values-it/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Avvio della configurazione…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configura dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Dispositivo connesso"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Connesso a \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Impossibile connettere"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Impossibile connettersi"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Prova a eseguire l\'accoppiamento manuale con il dispositivo"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prova a impostare il dispositivo sulla modalità di accoppiamento"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivi nelle vicinanze"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivi collegati all\'account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Disposit. salvato disponibile"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nelle vicinanze"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivi"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Connessione in corso"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batteria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Fine"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Salva"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Connetti"</string>
diff --git a/nearby/halfsheet/res/values-iw/strings.xml b/nearby/halfsheet/res/values-iw/strings.xml
index e6ff9b9..61724f0 100644
--- a/nearby/halfsheet/res/values-iw/strings.xml
+++ b/nearby/halfsheet/res/values-iw/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ההגדרה מתבצעת…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"הגדרת המכשיר"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"המכשיר מחובר"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"יש חיבור אל \'%s\'"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"לא ניתן להתחבר"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"לא ניתן להתחבר"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"כדאי לנסות לבצע התאמה ידנית למכשיר"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"כדאי לנסות להעביר את המכשיר למצב התאמה"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"מכשירים בהישג יד"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"מכשירים המחוברים לחשבון שלך"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"המכשיר ששמרת זמין"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"בקרבת מקום"</string>
+ <string name="common_devices" msgid="2635603125608104442">"מכשירים"</string>
+ <string name="common_connecting" msgid="160531481424245303">"מתבצעת התחברות…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"טעינת הסוללה: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"סיום"</string>
<string name="paring_action_save" msgid="6259357442067880136">"שמירה"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"התחברות"</string>
diff --git a/nearby/halfsheet/res/values-ja/strings.xml b/nearby/halfsheet/res/values-ja/strings.xml
index a429b7e..3168bda 100644
--- a/nearby/halfsheet/res/values-ja/strings.xml
+++ b/nearby/halfsheet/res/values-ja/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"セットアップを開始中…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"デバイスのセットアップ"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"デバイス接続完了"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"「%s」に接続しました"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"接続エラー"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"接続できません"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"手動でデバイスとペア設定してみてください"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"デバイスをペア設定モードにしてください"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"近接するデバイス"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"アカウントと接続済みのデバイス"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"保存済みのデバイスがあります"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"周辺ユーザーとの共有"</string>
+ <string name="common_devices" msgid="2635603125608104442">"デバイス"</string>
+ <string name="common_connecting" msgid="160531481424245303">"接続しています…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"バッテリー: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"完了"</string>
<string name="paring_action_save" msgid="6259357442067880136">"保存"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"接続"</string>
diff --git a/nearby/halfsheet/res/values-ka/strings.xml b/nearby/halfsheet/res/values-ka/strings.xml
index 4353ae9..a9ee648 100644
--- a/nearby/halfsheet/res/values-ka/strings.xml
+++ b/nearby/halfsheet/res/values-ka/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"დაყენება იწყება…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"მოწყობილობის დაყენება"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"მოწყობილობა დაკავშირებულია"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"დაკავშირებულია „%s“-თან"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"დაკავშირება ვერ მოხერხდა"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"დაკავშირება ვერ ხერხდება"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ცადეთ მოწყობილობასთან ხელით დაწყვილება"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ცადეთ მოწყობილობის გადაყვანა დაწყვილების რეჟიმზე"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ხელმისაწვდომი მოწყობილობები"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"მოწყობილობები თქვენი ანგარიშით"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"შენახული მოწყობილობა ხელმისაწვდომია"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"ახლომახლო"</string>
+ <string name="common_devices" msgid="2635603125608104442">"მოწყობილობები"</string>
+ <string name="common_connecting" msgid="160531481424245303">"მიმდინარეობს დაკავშირება…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ბატარეა: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"მზადაა"</string>
<string name="paring_action_save" msgid="6259357442067880136">"შენახვა"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"დაკავშირება"</string>
diff --git a/nearby/halfsheet/res/values-kk/strings.xml b/nearby/halfsheet/res/values-kk/strings.xml
index 98d8073..6e1a0bd 100644
--- a/nearby/halfsheet/res/values-kk/strings.xml
+++ b/nearby/halfsheet/res/values-kk/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Реттеу басталуда…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Құрылғыны реттеу"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Құрылғы байланыстырылды"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"\"%s\" құрылғысымен байланыстырылды"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Қосылмады"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Қосылу мүмкін емес"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Құрылғыны қолмен жұптап көріңіз."</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Құрылғыны жұптау режиміне қойып көріңіз."</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Қолжетімді құрылғылар"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Аккаунтпен байланыстырылған құрылғылар"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Сақталған құрылғы қолжетімді"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Маңайдағы"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Құрылғылар"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Жалғанып жатыр…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батарея: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Дайын"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Сақтау"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Қосу"</string>
diff --git a/nearby/halfsheet/res/values-km/strings.xml b/nearby/halfsheet/res/values-km/strings.xml
index 85e39db..deb6504 100644
--- a/nearby/halfsheet/res/values-km/strings.xml
+++ b/nearby/halfsheet/res/values-km/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"កំពុងចាប់ផ្ដើមរៀបចំ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"រៀបចំឧបករណ៍"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"បានភ្ជាប់ឧបករណ៍"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"បានភ្ជាប់ជាមួយ “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"មិនអាចភ្ជាប់បានទេ"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"មិនអាចភ្ជាប់បានទេ"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"សាកល្បងផ្គូផ្គងដោយផ្ទាល់ទៅឧបករណ៍"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"សាកល្បងកំណត់ឧបករណ៍ឱ្យប្រើមុខងារផ្គូផ្គង"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ឧបករណ៍នៅក្បែរដៃ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ឧបករណ៍ភ្ជាប់ជាមួយគណនីរបស់អ្នក"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"ឧបករណ៍ដែលអ្នកបានរក្សាទុកអាចប្រើបានហើយ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"នៅជិត"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ឧបករណ៍"</string>
+ <string name="common_connecting" msgid="160531481424245303">"កំពុងភ្ជាប់…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ថ្ម៖ %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"រួចរាល់"</string>
<string name="paring_action_save" msgid="6259357442067880136">"រក្សាទុក"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ភ្ជាប់"</string>
diff --git a/nearby/halfsheet/res/values-kn/strings.xml b/nearby/halfsheet/res/values-kn/strings.xml
index fb62bb1..87b4fe3 100644
--- a/nearby/halfsheet/res/values-kn/strings.xml
+++ b/nearby/halfsheet/res/values-kn/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ಸೆಟಪ್ ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ಸಾಧನವನ್ನು ಸೆಟಪ್ ಮಾಡಿ"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ಸಾಧನವನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ಸಾಧನಕ್ಕೆ ಹಸ್ತಚಾಲಿತವಾಗಿ ಜೋಡಿಸಲು ಪ್ರಯತ್ನಿಸಿ"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ಜೋಡಿಸುವಿಕೆ ಮೋಡ್ನಲ್ಲಿ ಸಾಧನವನ್ನು ಇರಿಸಲು ಪ್ರಯತ್ನಿಸಿ"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ವ್ಯಾಪ್ತಿಯಲ್ಲಿರುವ ಸಾಧನಗಳು"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಪರ್ಕಿತವಾಗಿರುವ ಸಾಧನಗಳು"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"ಉಳಿಸಲಾದ ನಿಮ್ಮ ಸಾಧನವು ಲಭ್ಯವಿದೆ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"ಸಮೀಪದಲ್ಲಿರುವುದು"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ಸಾಧನಗಳು"</string>
+ <string name="common_connecting" msgid="160531481424245303">"ಕನೆಕ್ಟ್ ಆಗುತ್ತಿದೆ…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ಬ್ಯಾಟರಿ: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ಮುಗಿದಿದೆ"</string>
<string name="paring_action_save" msgid="6259357442067880136">"ಉಳಿಸಿ"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
diff --git a/nearby/halfsheet/res/values-ko/strings.xml b/nearby/halfsheet/res/values-ko/strings.xml
index c94ff76..37d50da 100644
--- a/nearby/halfsheet/res/values-ko/strings.xml
+++ b/nearby/halfsheet/res/values-ko/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"설정을 시작하는 중…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"기기 설정"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"기기 연결됨"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"\'%s\'에 연결됨"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"연결할 수 없음"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"연결할 수 없음"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"기기에 수동으로 페어링을 시도해 보세요."</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"기기를 페어링 모드로 전환하세요."</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"연결 가능 기기"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"내 계정에 연결된 기기"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"저장된 기기 사용 가능"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nearby"</string>
+ <string name="common_devices" msgid="2635603125608104442">"기기"</string>
+ <string name="common_connecting" msgid="160531481424245303">"연결 중…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"배터리: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"완료"</string>
<string name="paring_action_save" msgid="6259357442067880136">"저장"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"연결"</string>
diff --git a/nearby/halfsheet/res/values-ky/strings.xml b/nearby/halfsheet/res/values-ky/strings.xml
index b0dfe20..b6aa409 100644
--- a/nearby/halfsheet/res/values-ky/strings.xml
+++ b/nearby/halfsheet/res/values-ky/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Жөндөлүп баштады…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Түзмөктү жөндөө"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Түзмөк туташты"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” түзмөгүнө туташты"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Туташпай койду"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Туташпай жатат"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Түзмөккө кол менен жупташтырып көрүңүз"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Түзмөктү Байланыштыруу режимине коюп көрүңүз"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Жеткиликтүү түзмөктөр"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Аккаунтуңузга кирип турган түзмөктөр"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Сакталган түзмөгүңүз жеткиликтүү"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Жакын жерде"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Түзмөктөр"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Туташууда…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батарея: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Бүттү"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Сактоо"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Туташуу"</string>
diff --git a/nearby/halfsheet/res/values-lo/strings.xml b/nearby/halfsheet/res/values-lo/strings.xml
index 9c945b2..cbc7601 100644
--- a/nearby/halfsheet/res/values-lo/strings.xml
+++ b/nearby/halfsheet/res/values-lo/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ກຳລັງເລີ່ມການຕັ້ງຄ່າ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ຕັ້ງຄ່າອຸປະກອນ"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ເຊື່ອມຕໍ່ອຸປະກອນແລ້ວ"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"ເຊື່ອມຕໍ່ກັບ “%s” ແລ້ວ"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ລອງຈັບຄູ່ອຸປະກອນດ້ວຍຕົນເອງ"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ໃຫ້ລອງຕັ້ງອຸປະກອນເປັນໂໝດຈັບຄູ່"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ອຸປະກອນພ້ອມໃຫ້ເຂົ້າເຖິງ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ອຸປະກອນທີ່ມີບັນຊີຂອງທ່ານ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"ອຸປະກອນທີ່ບັນທຶກໄວ້ຂອງທ່ານສາມາດໃຊ້ໄດ້"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"ໃກ້ຄຽງ"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ອຸປະກອນ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"ກຳລັງເຊື່ອມຕໍ່…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ແບັດເຕີຣີ: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ແລ້ວໆ"</string>
<string name="paring_action_save" msgid="6259357442067880136">"ບັນທຶກ"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ເຊື່ອມຕໍ່"</string>
diff --git a/nearby/halfsheet/res/values-lt/strings.xml b/nearby/halfsheet/res/values-lt/strings.xml
index 5dbad0a..29a9bc5 100644
--- a/nearby/halfsheet/res/values-lt/strings.xml
+++ b/nearby/halfsheet/res/values-lt/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Pradedama sąranka…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Įrenginio nustatymas"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Įrenginys prijungtas"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Prisijungta prie „%s“"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Prisijungti nepavyko"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nepavyko prisijungti"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Pabandykite neautomatiškai susieti įrenginį"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Pabandykite vėl įgalinti įrenginio susiejimo režimą"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Lengvai pasiekiami įrenginiai"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Įrenginiai su jūsų paskyra"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Išsaugotas įrenginys pasiekiamas"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Netoliese"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Įrenginiai"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Prisijungiama…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Akumuliatorius: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Atlikta"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Išsaugoti"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Prisijungti"</string>
diff --git a/nearby/halfsheet/res/values-lv/strings.xml b/nearby/halfsheet/res/values-lv/strings.xml
index a9e1bf9..9573357 100644
--- a/nearby/halfsheet/res/values-lv/strings.xml
+++ b/nearby/halfsheet/res/values-lv/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Tiek sākta iestatīšana…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Iestatiet ierīci"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Ierīce ir pievienota"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Izveidots savienojums ar ierīci “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nevarēja izveidot savienojumu"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nevar izveidot savienojumu."</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Mēģiniet manuāli izveidot savienojumu pārī ar ierīci."</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Ieslēdziet ierīcē režīmu savienošanai pārī"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Sasniedzamas ierīces"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Ierīces ar jūsu kontu"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Jūsu saglabātā ierīce pieejama"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Tuvumā"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Ierīces"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Savienojuma izveide…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Akumulatora uzlādes līmenis: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Gatavs"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Saglabāt"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Izveidot savienojumu"</string>
diff --git a/nearby/halfsheet/res/values-mk/strings.xml b/nearby/halfsheet/res/values-mk/strings.xml
index e29dfa1..693f112 100644
--- a/nearby/halfsheet/res/values-mk/strings.xml
+++ b/nearby/halfsheet/res/values-mk/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Се започнува со поставување…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Поставете го уредот"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Уредот е поврзан"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Поврзан со „%s“"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Не може да се поврзе"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Не може да се поврзе"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Обидете се рачно да се спарите со уредот"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Пробајте да го ставите уредот во режим на спарување"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Уреди на дофат"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Уреди поврзани со вашата сметка"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Вашиот зачуван уред е достапен"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Во близина"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Уреди"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Се поврзува…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батерија: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Готово"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Зачувај"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Поврзи"</string>
diff --git a/nearby/halfsheet/res/values-ml/strings.xml b/nearby/halfsheet/res/values-ml/strings.xml
index cbc171b..56a2db2 100644
--- a/nearby/halfsheet/res/values-ml/strings.xml
+++ b/nearby/halfsheet/res/values-ml/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"സജ്ജീകരിക്കൽ ആരംഭിക്കുന്നു…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ഉപകരണം സജ്ജീകരിക്കുക"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ഉപകരണം കണക്റ്റ് ചെയ്തു"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” എന്നതിലേക്ക് കണക്റ്റ് ചെയ്തു"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"കണക്റ്റ് ചെയ്യാനായില്ല"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"കണക്റ്റ് ചെയ്യാനാകുന്നില്ല"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ഉപകരണം ജോടിയാക്കാൻ നേരിട്ട് ശ്രമിക്കുക"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ഉപകരണം ജോഡിയാക്കൽ മോഡിലേക്ക് മാറ്റിയ ശേഷം ശ്രമിക്കുക"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"പരിധിയിലുള്ള ഉപകരണങ്ങൾ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"അക്കൗണ്ട് ഉപയോഗിക്കുന്ന ഉപകരണങ്ങൾ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"സംരക്ഷിച്ച ഉപകരണം ലഭ്യമാണ്"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"സമീപമുള്ളവ"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ഉപകരണങ്ങൾ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"കണക്റ്റ് ചെയ്യുന്നു…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ബാറ്ററി: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"പൂർത്തിയായി"</string>
<string name="paring_action_save" msgid="6259357442067880136">"സംരക്ഷിക്കുക"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"കണക്റ്റ് ചെയ്യുക"</string>
diff --git a/nearby/halfsheet/res/values-mn/strings.xml b/nearby/halfsheet/res/values-mn/strings.xml
index 6d21eff..5a72ce3 100644
--- a/nearby/halfsheet/res/values-mn/strings.xml
+++ b/nearby/halfsheet/res/values-mn/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Тохируулгыг эхлүүлж байна…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Төхөөрөмж тохируулах"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Төхөөрөмж холбогдсон"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s”-д холбогдсон"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Холбогдож чадсангүй"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Холбогдох боломжгүй байна"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Төхөөрөмжийг гар аргаар хослуулна уу"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Төхөөрөмжийг хослуулах горимд оруулахаар оролдоно уу"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Хүрээн дэх төхөөрөмжүүд"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Таны бүртгэлтэй холбогдсон төхөөрөмж"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Таны хадгалсан төхөөрөмж бэлэн байна"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Ойролцоо"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Төхөөрөмж"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Холбогдож байна…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батарей: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Болсон"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Хадгалах"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Холбох"</string>
diff --git a/nearby/halfsheet/res/values-mr/strings.xml b/nearby/halfsheet/res/values-mr/strings.xml
index a3e1d7a..3eeb0ec 100644
--- a/nearby/halfsheet/res/values-mr/strings.xml
+++ b/nearby/halfsheet/res/values-mr/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"सेटअप सुरू करत आहे…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"डिव्हाइस सेट करा"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"डिव्हाइस कनेक्ट केले आहे"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"\"%s\" शी कनेक्ट केले आहे"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"कनेक्ट करता आले नाही"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"कनेक्ट करता आले नाही"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"डिव्हाइसशी मॅन्युअली पेअर करण्याचा प्रयत्न करा"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"डिव्हाइसला पेअरिंग मोडमध्ये ठेवण्याचा प्रयत्न करा"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"पुरेसे जवळ असलेले डिव्हाइस"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"तुमच्या खात्यासह असलेली डिव्हाइस"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"सेव्ह केलेले डिव्हाइस उपलब्ध"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"जवळपास"</string>
+ <string name="common_devices" msgid="2635603125608104442">"डिव्हाइस"</string>
+ <string name="common_connecting" msgid="160531481424245303">"कनेक्ट करत आहे…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"बॅटरी: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"पूर्ण झाले"</string>
<string name="paring_action_save" msgid="6259357442067880136">"सेव्ह करा"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"कनेक्ट करा"</string>
diff --git a/nearby/halfsheet/res/values-ms/strings.xml b/nearby/halfsheet/res/values-ms/strings.xml
index 4835c1b..0af903d 100644
--- a/nearby/halfsheet/res/values-ms/strings.xml
+++ b/nearby/halfsheet/res/values-ms/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Memulakan Persediaan…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Sediakan peranti"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Peranti disambungkan"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Disambungkan kepada “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Tidak dapat menyambung"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Tidak dapat menyambung"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Cuba gandingkan dengan peranti secara manual"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Cuba letakkan peranti dalam mod penggandingan"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Peranti dalam capaian"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Peranti dengan akaun anda"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Peranti disimpan anda tersedia"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Berdekatan"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Peranti"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Menyambung…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateri: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Selesai"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Simpan"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Sambung"</string>
diff --git a/nearby/halfsheet/res/values-my/strings.xml b/nearby/halfsheet/res/values-my/strings.xml
index 32c3105..306538f 100644
--- a/nearby/halfsheet/res/values-my/strings.xml
+++ b/nearby/halfsheet/res/values-my/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"စနစ်ထည့်သွင်းခြင်း စတင်နေသည်…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"စက်ကို စနစ်ထည့်သွင်းရန်"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"စက်ကို ချိတ်ဆက်လိုက်ပြီ"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” သို့ ချိတ်ဆက်ထားသည်"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"ချိတ်ဆက်၍မရပါ"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"ချိတ်ဆက်၍ မရပါ"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"စက်ကို ကိုယ်တိုင်တွဲချိတ်ကြည့်ပါ"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"စက်ကို တွဲချိတ်ခြင်းမုဒ်သို့ ထားကြည့်ပါ"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"လက်လှမ်းမီသည့် စက်များ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"သင့်အကောင့်ရှိသည့် စက်များ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"သင်သိမ်းထားသောစက် ရပါပြီ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"အနီးတစ်ဝိုက်"</string>
+ <string name="common_devices" msgid="2635603125608104442">"စက်များ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"ချိတ်ဆက်နေသည်…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ဘက်ထရီ− %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ပြီးပြီ"</string>
<string name="paring_action_save" msgid="6259357442067880136">"သိမ်းရန်"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ချိတ်ဆက်ရန်"</string>
diff --git a/nearby/halfsheet/res/values-nb/strings.xml b/nearby/halfsheet/res/values-nb/strings.xml
index 9d72565..72a2ab7 100644
--- a/nearby/halfsheet/res/values-nb/strings.xml
+++ b/nearby/halfsheet/res/values-nb/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Starter konfigureringen …"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Konfigurer enheten"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Enheten er tilkoblet"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Koblet til «%s»"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Kunne ikke koble til"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Kan ikke koble til"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Prøv manuell tilkobling til enheten"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prøv å sette enheten i tilkoblingsmodus"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Enheter innen rekkevidde"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Enheter med kontoen din"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Lagret enhet tilgjengelig"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"I nærheten"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Enheter"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Kobler til …"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batteri: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Ferdig"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Lagre"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Koble til"</string>
diff --git a/nearby/halfsheet/res/values-ne/strings.xml b/nearby/halfsheet/res/values-ne/strings.xml
index 1370412..2956768 100644
--- a/nearby/halfsheet/res/values-ne/strings.xml
+++ b/nearby/halfsheet/res/values-ne/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"सेटअप प्रक्रिया सुरु गरिँदै छ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"डिभाइस सेटअप गर्नुहोस्"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"डिभाइस कनेक्ट गरियो"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"\"%s\" मा कनेक्ट गरिएको छ"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"कनेक्ट गर्न सकिएन"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"कनेक्ट गर्न सकिएन"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"म्यानुअल तरिकाले डिभाइस कनेक्ट गरी हेर्नुहोस्"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"डिभाइस कनेक्ट गर्ने मोडमा राखी हेर्नुहोस्"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"कनेक्ट गर्न सकिने नजिकैका डिभाइसहरू"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"तपाईंको खातामा कनेक्ट गरिएका डिभाइस"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"तपाईंले सेभ गरेको डिभाइस उपलब्ध छ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"नजिकै"</string>
+ <string name="common_devices" msgid="2635603125608104442">"डिभाइसहरू"</string>
+ <string name="common_connecting" msgid="160531481424245303">"कनेक्ट गरिँदै छ…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ब्याट्री: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"सम्पन्न भयो"</string>
<string name="paring_action_save" msgid="6259357442067880136">"सेभ गर्नुहोस्"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"कनेक्ट गर्नुहोस्"</string>
diff --git a/nearby/halfsheet/res/values-night/colors.xml b/nearby/halfsheet/res/values-night/colors.xml
new file mode 100644
index 0000000..69b832a
--- /dev/null
+++ b/nearby/halfsheet/res/values-night/colors.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+ <!-- Use original background color -->
+ <color name="fast_pair_notification_background">#00000000</color>
+ <!-- Ignores NewApi as below system colors are available since API 31, and HalfSheet is always
+ running on T+ even though it has min_sdk 30 to match its containing APEX -->
+ <color name="fast_pair_half_sheet_button_color" tools:ignore="NewApi">
+ @android:color/system_accent1_100</color>
+ <color name="fast_pair_half_sheet_button_text" tools:ignore="NewApi">
+ @android:color/system_neutral1_50</color>
+ <color name="fast_pair_half_sheet_button_accent_text" tools:ignore="NewApi">
+ @android:color/system_neutral1_900</color>
+ <color name="fast_pair_progress_color" tools:ignore="NewApi">
+ @android:color/system_accent1_600</color>
+ <color name="fast_pair_half_sheet_subtitle_color" tools:ignore="NewApi">
+ @android:color/system_neutral2_200</color>
+ <color name="fast_pair_half_sheet_text_color" tools:ignore="NewApi">
+ @android:color/system_neutral1_50</color>
+ <color name="fast_pair_half_sheet_background" tools:ignore="NewApi">
+ @android:color/system_neutral1_800</color>
+
+ <!-- Fast Pair -->
+ <color name="fast_pair_primary_text">#FFFFFF</color>
+ <color name="fast_pair_notification_image_outline">#24FFFFFF</color>
+ <color name="fast_pair_battery_level_low">#F6AEA9</color>
+
+</resources>
+
diff --git a/nearby/halfsheet/res/values-nl/strings.xml b/nearby/halfsheet/res/values-nl/strings.xml
index 4eb7624..e956116 100644
--- a/nearby/halfsheet/res/values-nl/strings.xml
+++ b/nearby/halfsheet/res/values-nl/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Instellen starten…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Apparaat instellen"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Apparaat verbonden"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Verbonden met %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Kan geen verbinding maken"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Kan geen verbinding maken"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Probeer handmatig met het apparaat te koppelen"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Activeer de koppelingsstand van het apparaat"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Apparaten binnen bereik"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Apparaten met je account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Opgeslagen apparaat beschikbaar"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"In de buurt"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Apparaten"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Verbinden…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batterij: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Klaar"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Opslaan"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Verbinden"</string>
diff --git a/nearby/halfsheet/res/values-or/strings.xml b/nearby/halfsheet/res/values-or/strings.xml
index c5e8cfc..0ec472c 100644
--- a/nearby/halfsheet/res/values-or/strings.xml
+++ b/nearby/halfsheet/res/values-or/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ସେଟଅପ ଆରମ୍ଭ କରାଯାଉଛି…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ଡିଭାଇସ ସେଟ ଅପ କରନ୍ତୁ"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ଡିଭାଇସ ସଂଯୁକ୍ତ ହୋଇଛି"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” ସହ କନେକ୍ଟ କରାଯାଇଛି"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"ସଂଯୋଗ କରାଯାଇପାରିଲା ନାହିଁ"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"କନେକ୍ଟ କରିବାରେ ଅସମର୍ଥ"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ଡିଭାଇସ ସହ ମାନୁଆଲୀ ପେୟାର କରିବା ପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ଡିଭାଇସକୁ ପେୟାରିଂ ମୋଡରେ ରଖିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ପହଞ୍ଚ ଭିତରେ ଥିବା ଡିଭାଇସଗୁଡ଼ିକ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ଆପଣଙ୍କ ଆକାଉଣ୍ଟ ସହ ଥିବା ଡିଭାଇସଗୁଡ଼ିକ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"ସେଭ ଥିବା ଆପଣଙ୍କ ଡିଭାଇସ ଉପଲବ୍ଧ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"ଆଖପାଖର"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ଡିଭାଇସଗୁଡ଼ିକ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"କନେକ୍ଟ କରାଯାଉଛି…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ବେଟେରୀ: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ହୋଇଗଲା"</string>
<string name="paring_action_save" msgid="6259357442067880136">"ସେଭ କରନ୍ତୁ"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ସଂଯୋଗ କରନ୍ତୁ"</string>
diff --git a/nearby/halfsheet/res/values-pa/strings.xml b/nearby/halfsheet/res/values-pa/strings.xml
index f0523a3..4eb0553 100644
--- a/nearby/halfsheet/res/values-pa/strings.xml
+++ b/nearby/halfsheet/res/values-pa/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"ਸੈੱਟਅੱਪ ਸ਼ੁਰੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ਡੀਵਾਈਸ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"ਡੀਵਾਈਸ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ਡੀਵਾਈਸ ਨਾਲ ਹੱਥੀਂ ਜੋੜਾਬੱਧ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"ਡੀਵਾਈਸ ਨੂੰ ਜੋੜਾਬੱਧਕਰਨ ਮੋਡ ਵਿੱਚ ਰੱਖਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ਡੀਵਾਈਸ ਜੋ ਪਹੁੰਚ ਅੰਦਰ ਹਨ"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ਤੁਹਾਡੇ ਖਾਤੇ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"ਰੱਖਿਅਤ ਕੀਤਾ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੈ"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"ਨਜ਼ਦੀਕੀ"</string>
+ <string name="common_devices" msgid="2635603125608104442">"ਡੀਵਾਈਸ"</string>
+ <string name="common_connecting" msgid="160531481424245303">"ਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"ਬੈਟਰੀ: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ਹੋ ਗਿਆ"</string>
<string name="paring_action_save" msgid="6259357442067880136">"ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"ਕਨੈਕਟ ਕਰੋ"</string>
diff --git a/nearby/halfsheet/res/values-pl/strings.xml b/nearby/halfsheet/res/values-pl/strings.xml
index 5abf5fd..5082e18 100644
--- a/nearby/halfsheet/res/values-pl/strings.xml
+++ b/nearby/halfsheet/res/values-pl/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Rozpoczynam konfigurowanie…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Skonfiguruj urządzenie"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Urządzenie połączone"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Połączono z: „%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nie udało się połączyć"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nie udało się połączyć"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Spróbuj ręcznie sparować urządzenie"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Włącz na urządzeniu tryb parowania"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Urządzenia w zasięgu"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Urządzenia z Twoim kontem"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Zapisane urządzenie dostępne"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"W pobliżu"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Urządzenia"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Łączę…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Gotowe"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Zapisz"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Połącz"</string>
diff --git a/nearby/halfsheet/res/values-pt-rBR/strings.xml b/nearby/halfsheet/res/values-pt-rBR/strings.xml
index b021b39..15d29d2 100644
--- a/nearby/halfsheet/res/values-pt-rBR/strings.xml
+++ b/nearby/halfsheet/res/values-pt-rBR/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iniciando a configuração…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configurar dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Dispositivo conectado"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Conectado ao dispositivo \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Erro ao conectar"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Não foi possível conectar"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Tente parear o dispositivo manualmente"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Coloque o dispositivo no modo de pareamento"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivos ao alcance"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivos conectados à sua conta"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Dispositivo salvo disponível"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Por perto"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivos"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Conectando…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Concluído"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Salvar"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Conectar"</string>
diff --git a/nearby/halfsheet/res/values-pt-rPT/strings.xml b/nearby/halfsheet/res/values-pt-rPT/strings.xml
index 3285c73..ab8decf 100644
--- a/nearby/halfsheet/res/values-pt-rPT/strings.xml
+++ b/nearby/halfsheet/res/values-pt-rPT/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"A iniciar a configuração…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configure o dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Dispositivo ligado"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Ligado a \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Não foi possível ligar"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Impossível ligar"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Experimente sincronizar manualmente com o dispositivo"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Experimente ativar o modo de sincronização no dispositivo"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivos ao alcance"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivos com a sua conta"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Disposit. guardado disponível"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Partilha"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivos"</string>
+ <string name="common_connecting" msgid="160531481424245303">"A ligar…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Concluir"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Guardar"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Ligar"</string>
diff --git a/nearby/halfsheet/res/values-pt/strings.xml b/nearby/halfsheet/res/values-pt/strings.xml
index b021b39..15d29d2 100644
--- a/nearby/halfsheet/res/values-pt/strings.xml
+++ b/nearby/halfsheet/res/values-pt/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iniciando a configuração…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configurar dispositivo"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Dispositivo conectado"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Conectado ao dispositivo \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Erro ao conectar"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Não foi possível conectar"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Tente parear o dispositivo manualmente"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Coloque o dispositivo no modo de pareamento"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispositivos ao alcance"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispositivos conectados à sua conta"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Dispositivo salvo disponível"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Por perto"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispositivos"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Conectando…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Concluído"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Salvar"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Conectar"</string>
diff --git a/nearby/halfsheet/res/values-ro/strings.xml b/nearby/halfsheet/res/values-ro/strings.xml
index 189f698..0335d01 100644
--- a/nearby/halfsheet/res/values-ro/strings.xml
+++ b/nearby/halfsheet/res/values-ro/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Începe configurarea…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Configurează dispozitivul"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Dispozitivul s-a conectat"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Conectat la %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nu s-a putut conecta"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nu se poate conecta"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Încearcă asocierea manuală cu dispozitivul"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Încearcă să pui dispozitivul în modul de asociere"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Dispozitive în vecinătate"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Dispozitive conectate cu contul"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Dispozitivul este disponibil"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"În apropiere"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Dispozitive"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Se conectează…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterie: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Gata"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Salvează"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Conectează"</string>
diff --git a/nearby/halfsheet/res/values-ru/strings.xml b/nearby/halfsheet/res/values-ru/strings.xml
index ee869df..d90b644 100644
--- a/nearby/halfsheet/res/values-ru/strings.xml
+++ b/nearby/halfsheet/res/values-ru/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Начинаем настройку…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Настройка устройства"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Устройство подключено"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Подключено к устройству \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Ошибка подключения"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Не удалось подключиться"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Попробуйте подключиться к устройству вручную."</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Переведите устройство в режим подключения."</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Устройства в зоне охвата"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Устройства с вашим аккаунтом"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Доступно сохранен. устройство"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Мое окружение"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Устройства"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Подключение…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батарея: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Готово"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Сохранить"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Подключить"</string>
diff --git a/nearby/halfsheet/res/values-si/strings.xml b/nearby/halfsheet/res/values-si/strings.xml
index f4274c2..c9b96bb 100644
--- a/nearby/halfsheet/res/values-si/strings.xml
+++ b/nearby/halfsheet/res/values-si/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"පිහිටුවීම ආරම්භ කරමින්…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"උපාංගය පිහිටුවන්න"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"උපාංගය සම්බන්ධිතයි"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” වෙත සම්බන්ධ විය"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"සම්බන්ධ කළ නොහැකි විය"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"සම්බන්ධ වීමට නොහැකි වේ"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"උපාංගය වෙත හස්තීයව යුගල කිරීමට උත්සාහ කරන්න"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"උපාංගය යුගල කිරීමේ ප්රකාරයට දැමීමට උත්සාහ කරන්න"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"ළඟා විය හැකි උපාංග"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"ඔබේ ගිණුම සමග උපාංග"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"ඔබේ සුරැකි උපාංගය ලබා ගත හැක"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"අවට"</string>
+ <string name="common_devices" msgid="2635603125608104442">"උපාංග"</string>
+ <string name="common_connecting" msgid="160531481424245303">"සම්බන්ධ වෙමින්…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"බැටරිය: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"නිමයි"</string>
<string name="paring_action_save" msgid="6259357442067880136">"සුරකින්න"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"සම්බන්ධ කරන්න"</string>
diff --git a/nearby/halfsheet/res/values-sk/strings.xml b/nearby/halfsheet/res/values-sk/strings.xml
index 46c45af..f7ab21f 100644
--- a/nearby/halfsheet/res/values-sk/strings.xml
+++ b/nearby/halfsheet/res/values-sk/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Spúšťa sa nastavenie…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Nastavte zariadenie"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Zariadenie bolo pripojené"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Pripojené k zariadeniu %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nepodarilo sa pripojiť"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nepodarilo sa pripojiť"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Skúste zariadenie spárovať ručne"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Prepnite zariadenie do párovacieho režimu"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Zariadenia v dosahu"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Zariadenia s vaším účtom"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Uložené zariadenie je dostupné"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Nablízku"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Zariadenia"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Pripája sa…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batéria: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Hotovo"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Uložiť"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Pripojiť"</string>
diff --git a/nearby/halfsheet/res/values-sl/strings.xml b/nearby/halfsheet/res/values-sl/strings.xml
index e4f3c91..9e9357c 100644
--- a/nearby/halfsheet/res/values-sl/strings.xml
+++ b/nearby/halfsheet/res/values-sl/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Začetek nastavitve …"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Nastavitev naprave"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Naprava je povezana"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Povezano z napravo »%s«"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Povezava ni mogoča"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Povezave ni mogoče vzpostaviti"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Poskusite ročno seznaniti napravo."</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Poskusite napravo preklopiti v način za seznanjanje."</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Naprave znotraj dosega"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Naprave z vašim računom"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Shranjena naprava je na voljo"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Bližina"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Naprave"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Povezovanje …"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterija: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Končano"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Shrani"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Poveži"</string>
diff --git a/nearby/halfsheet/res/values-sq/strings.xml b/nearby/halfsheet/res/values-sq/strings.xml
index 9265d1f..538e9d6 100644
--- a/nearby/halfsheet/res/values-sq/strings.xml
+++ b/nearby/halfsheet/res/values-sq/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Po nis konfigurimin…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Konfiguro pajisjen"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Pajisja u lidh"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"U lidh me “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Nuk mund të lidhej"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Nuk mund të lidhet"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Provo të çiftosh me pajisjen manualisht"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Provo ta vendosësh pajisjen në modalitetin e çiftimit"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Pajisjet që mund të arrish"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Pajisjet me llogarinë tënde"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Pajisja jote e ruajtur ofrohet"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Në afërsi"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Pajisjet"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Po lidhet…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Bateria: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"U krye"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Ruaj"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Lidh"</string>
diff --git a/nearby/halfsheet/res/values-sr/strings.xml b/nearby/halfsheet/res/values-sr/strings.xml
index 094be03..c4bcd19 100644
--- a/nearby/halfsheet/res/values-sr/strings.xml
+++ b/nearby/halfsheet/res/values-sr/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Подешавање се покреће…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Подесите уређај"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Уређај је повезан"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Повезани сте са уређајем %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Повезивање није успело"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Повезивање није успело"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Пробајте да упарите ручно са уређајем"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Пробајте да пребаците уређај у режим упаривања"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Уређаји у домету"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Уређаји повезани са налогом"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Сачувани уређај је доступан"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"У близини"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Уређаји"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Повезује се…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Батерија: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Готово"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Сачувај"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Повежи"</string>
diff --git a/nearby/halfsheet/res/values-sv/strings.xml b/nearby/halfsheet/res/values-sv/strings.xml
index 297b7bc..b00091c 100644
--- a/nearby/halfsheet/res/values-sv/strings.xml
+++ b/nearby/halfsheet/res/values-sv/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Konfigureringen startas …"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Konfigurera enheten"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Enheten är ansluten"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Ansluten till %s"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Det gick inte att ansluta"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Det går inte att ansluta"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Testa att parkoppla enheten manuellt"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Testa att aktivera parkopplingsläget på enheten"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Enheter inom räckvidd"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Enheter med ditt konto"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"En sparad enhet är tillgänglig"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Närdelning"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Enheter"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Ansluter …"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batteri: %d %%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Klar"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Spara"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Anslut"</string>
diff --git a/nearby/halfsheet/res/values-sw/strings.xml b/nearby/halfsheet/res/values-sw/strings.xml
index bf0bfeb..238a288 100644
--- a/nearby/halfsheet/res/values-sw/strings.xml
+++ b/nearby/halfsheet/res/values-sw/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Inaanza Kuweka Mipangilio…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Weka mipangilio ya kifaa"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Kifaa kimeunganishwa"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Imeunganishwa kwenye “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Imeshindwa kuunganisha"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Imeshindwa kuunganisha"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Jaribu kuoanisha mwenyewe kwenye kifaa"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Jaribu kuweka kifaa katika hali ya kuoanisha"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Vifaa vilivyo karibu nawe"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Vifaa vilivyounganishwa kwenye akaunti yako"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Kifaa ulichohifadhi kinapatikana"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Uhamishaji wa Karibu"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Vifaa"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Inaunganisha…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Betri: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Imemaliza"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Hifadhi"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Unganisha"</string>
diff --git a/nearby/halfsheet/res/values-ta/strings.xml b/nearby/halfsheet/res/values-ta/strings.xml
index dfd67a6..baadcc2 100644
--- a/nearby/halfsheet/res/values-ta/strings.xml
+++ b/nearby/halfsheet/res/values-ta/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"அமைவைத் தொடங்குகிறது…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"சாதனத்தை அமையுங்கள்"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"சாதனம் இணைக்கப்பட்டது"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s” உடன் இணைக்கப்பட்டது"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"இணைக்க முடியவில்லை"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"இணைக்க முடியவில்லை"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"சாதனத்துடன் நீங்களாகவே இணைக்க முயலவும்"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"சாதனத்தை \'இணைத்தல் பயன்முறையில்\' வைக்கவும்"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"தொடர்பு வரம்பிலுள்ள சாதனங்கள்"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"உங்கள் கணக்குடன் இணைந்துள்ள சாதனங்கள்"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"நீங்கள் சேமித்த சாதனம் உள்ளது"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"அருகில் பகிர்தல்"</string>
+ <string name="common_devices" msgid="2635603125608104442">"சாதனங்கள்"</string>
+ <string name="common_connecting" msgid="160531481424245303">"இணைக்கிறது…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"பேட்டரி: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"முடிந்தது"</string>
<string name="paring_action_save" msgid="6259357442067880136">"சேமி"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"இணை"</string>
diff --git a/nearby/halfsheet/res/values-te/strings.xml b/nearby/halfsheet/res/values-te/strings.xml
index 87be145..cb8f91b 100644
--- a/nearby/halfsheet/res/values-te/strings.xml
+++ b/nearby/halfsheet/res/values-te/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"సెటప్ ప్రారంభమవుతోంది…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"పరికరాన్ని సెటప్ చేయండి"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"పరికరం కనెక్ట్ చేయబడింది"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"“%s”కు కనెక్ట్ చేయబడింది"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"కనెక్ట్ చేయలేకపోయింది"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"పరికరానికి మాన్యువల్గా పెయిరింగ్ చేయడానికి ట్రై చేయండి"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"పరికరాన్ని పెయిరింగ్ మోడ్లో ఉంచడానికి ట్రై చేయండి"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"అందుబాటులో ఉన్న పరికరాలు"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"మీ ఖాతా ఉన్న పరికరాలు"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"మీ సేవ్ చేసిన పరికరం అందుబాటులో ఉంది"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"సమీపం"</string>
+ <string name="common_devices" msgid="2635603125608104442">"పరికరాలు"</string>
+ <string name="common_connecting" msgid="160531481424245303">"కనెక్ట్ అవుతోంది…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"బ్యాటరీ: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"పూర్తయింది"</string>
<string name="paring_action_save" msgid="6259357442067880136">"సేవ్ చేయండి"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"కనెక్ట్ చేయండి"</string>
diff --git a/nearby/halfsheet/res/values-th/strings.xml b/nearby/halfsheet/res/values-th/strings.xml
index bc4296b..f5c5c2e 100644
--- a/nearby/halfsheet/res/values-th/strings.xml
+++ b/nearby/halfsheet/res/values-th/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"กำลังเริ่มการตั้งค่า…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"ตั้งค่าอุปกรณ์"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"เชื่อมต่ออุปกรณ์แล้ว"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"เชื่อมต่อกับ \"%s\" แล้ว"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"เชื่อมต่อไม่ได้"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"เชื่อมต่อไม่ได้"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"ลองจับคู่อุปกรณ์ด้วยตนเอง"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"พยายามนำอุปกรณ์เข้าสู่โหมดการจับคู่"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"อุปกรณ์ที่อยู่ติดกัน"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"อุปกรณ์ที่มีบัญชีของคุณ"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"อุปกรณ์ที่บันทึกพร้อมใช้แล้ว"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"ใกล้เคียง"</string>
+ <string name="common_devices" msgid="2635603125608104442">"อุปกรณ์"</string>
+ <string name="common_connecting" msgid="160531481424245303">"กำลังเชื่อมต่อ…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"แบตเตอรี่: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"เสร็จสิ้น"</string>
<string name="paring_action_save" msgid="6259357442067880136">"บันทึก"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"เชื่อมต่อ"</string>
diff --git a/nearby/halfsheet/res/values-tl/strings.xml b/nearby/halfsheet/res/values-tl/strings.xml
index a6de0e8..a546da6 100644
--- a/nearby/halfsheet/res/values-tl/strings.xml
+++ b/nearby/halfsheet/res/values-tl/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Sinisimulan ang Pag-set Up…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"I-set up ang device"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Naikonekta na ang device"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Nakakonekta sa “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Hindi makakonekta"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Hindi makakonekta"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Subukang manual na magpares sa device"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Subukang ilagay sa pairing mode ang device"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Mga naaabot na device"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Mga device sa iyong account"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Available ang iyong na-save na device"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Kalapit"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Mga Device"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Kumokonekta…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Baterya: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Tapos na"</string>
<string name="paring_action_save" msgid="6259357442067880136">"I-save"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Kumonekta"</string>
diff --git a/nearby/halfsheet/res/values-tr/strings.xml b/nearby/halfsheet/res/values-tr/strings.xml
index cd5a6ea..a54c5e7 100644
--- a/nearby/halfsheet/res/values-tr/strings.xml
+++ b/nearby/halfsheet/res/values-tr/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Kurulum Başlatılıyor…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Cihazı kur"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Cihaz bağlandı"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"\"%s\" cihazına bağlanıldı"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Bağlanamadı"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Bağlantı kurulamadı"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Cihazla manuel olarak eşlemeyi deneyin"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Cihazı eşleme moduna geçirmeyi deneyin"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Erişilebilecek cihazlar"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Hesabınıza bağlı cihazlar"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Kayıtlı cihazınız kullanılabilir"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Yakındaki"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Cihazlar"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Bağlanıyor…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Pil seviyesi: %%%d"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Bitti"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Kaydet"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Bağlan"</string>
diff --git a/nearby/halfsheet/res/values-uk/strings.xml b/nearby/halfsheet/res/values-uk/strings.xml
index 242ca07..ab73c1f 100644
--- a/nearby/halfsheet/res/values-uk/strings.xml
+++ b/nearby/halfsheet/res/values-uk/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Запуск налаштування…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Налаштуйте пристрій"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Пристрій підключено"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Підключено до пристрою \"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Не вдалося підключити"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Не вдалося підключитися"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Спробуйте підключитися до пристрою вручну"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Спробуйте ввімкнути на пристрої режим підключення"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Пристрої в радіусі дії"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Пристрої з вашим обліковим записом"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Збережений пристрій доступний"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Поблизу"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Пристрої"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Підключення…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Акумулятор: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Готово"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Зберегти"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Підключити"</string>
diff --git a/nearby/halfsheet/res/values-ur/strings.xml b/nearby/halfsheet/res/values-ur/strings.xml
index 4a4a59c..a2b2038 100644
--- a/nearby/halfsheet/res/values-ur/strings.xml
+++ b/nearby/halfsheet/res/values-ur/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"سیٹ اپ شروع ہو رہا ہے…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"آلہ سیٹ اپ کریں"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"آلہ منسلک ہے"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"\"\"%s سے منسلک ہے"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"منسلک نہیں ہو سکا"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"منسلک ہونے سے قاصر"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"دستی طور پر آلے کے ساتھ جوڑا بنانا آزمائیں"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"آلے کو جوڑا بنانے والے موڈ میں رکھ کر آزمائیں"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"رسائی کے اندر آلات"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"آپ کے اکاؤنٹ سے منسلک آلات"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"آپ کا محفوظ کردہ آلہ دستیاب ہے"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"قریبی"</string>
+ <string name="common_devices" msgid="2635603125608104442">"آلات"</string>
+ <string name="common_connecting" msgid="160531481424245303">"منسلک ہو رہا ہے…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"بیٹری: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"ہو گیا"</string>
<string name="paring_action_save" msgid="6259357442067880136">"محفوظ کریں"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"منسلک کریں"</string>
diff --git a/nearby/halfsheet/res/values-uz/strings.xml b/nearby/halfsheet/res/values-uz/strings.xml
index 420512d..70c190a 100644
--- a/nearby/halfsheet/res/values-uz/strings.xml
+++ b/nearby/halfsheet/res/values-uz/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Sozlash boshlandi…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Qurilmani sozlash"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Qurilma ulandi"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Bunga ulandi: “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Ulanmadi"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Ulanmadi"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Qurilmangizga odatiy usulda ulaning"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Qurilmada ulanish rejimini yoqing"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Atrofdagi qurilmalar"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Hisobingizga ulangan qurilmalar"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Saqlangan qurilmangiz mavjud"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Yaqin-atrofda"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Qurilmalar"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Ulanmoqda…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Batareya: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Tayyor"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Saqlash"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Ulanish"</string>
diff --git a/nearby/halfsheet/res/values-vi/strings.xml b/nearby/halfsheet/res/values-vi/strings.xml
index 9c1e052..e2ea467 100644
--- a/nearby/halfsheet/res/values-vi/strings.xml
+++ b/nearby/halfsheet/res/values-vi/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Đang bắt đầu thiết lập…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Thiết lập thiết bị"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Đã kết nối thiết bị"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Đã kết nối với “%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Không kết nối được"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Không thể kết nối"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Hãy thử ghép nối thủ công với thiết bị"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Hãy thử đưa thiết bị này vào chế độ ghép nối"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Thiết bị trong tầm tay"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Các thiết bị có tài khoản của bạn"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Thiết bị đã lưu của bạn có sẵn"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Lân cận"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Thiết bị"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Đang kết nối…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Pin: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Xong"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Lưu"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Kết nối"</string>
diff --git a/nearby/halfsheet/res/values-zh-rCN/strings.xml b/nearby/halfsheet/res/values-zh-rCN/strings.xml
index 482b5c4..8117bac 100644
--- a/nearby/halfsheet/res/values-zh-rCN/strings.xml
+++ b/nearby/halfsheet/res/values-zh-rCN/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"正在启动设置…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"设置设备"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"设备已连接"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"已连接到“%s”"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"无法连接"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"无法连接"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"请尝试手动与该设备配对"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"请尝试让设备进入配对模式"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"附近的设备"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"与您的帐号相关联的设备"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"您保存的设备已可供使用"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"附近"</string>
+ <string name="common_devices" msgid="2635603125608104442">"设备"</string>
+ <string name="common_connecting" msgid="160531481424245303">"正在连接…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"电量:%d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"完成"</string>
<string name="paring_action_save" msgid="6259357442067880136">"保存"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"连接"</string>
diff --git a/nearby/halfsheet/res/values-zh-rHK/strings.xml b/nearby/halfsheet/res/values-zh-rHK/strings.xml
index 3ca73e6..d934f88 100644
--- a/nearby/halfsheet/res/values-zh-rHK/strings.xml
+++ b/nearby/halfsheet/res/values-zh-rHK/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"開始設定…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"設定裝置"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"已連接裝置"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"已連線至「%s」"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"無法連接"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"無法連線"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"嘗試手動配對裝置"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"嘗試讓裝置進入配對模式"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"附近的裝置"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"已連結您帳戶的裝置"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"您儲存的裝置已可使用"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"咫尺共享"</string>
+ <string name="common_devices" msgid="2635603125608104442">"裝置"</string>
+ <string name="common_connecting" msgid="160531481424245303">"正在連接…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"電量:%d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"完成"</string>
<string name="paring_action_save" msgid="6259357442067880136">"儲存"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"連接"</string>
diff --git a/nearby/halfsheet/res/values-zh-rTW/strings.xml b/nearby/halfsheet/res/values-zh-rTW/strings.xml
index b4e680d..0c90ebb 100644
--- a/nearby/halfsheet/res/values-zh-rTW/strings.xml
+++ b/nearby/halfsheet/res/values-zh-rTW/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"正在啟動設定程序…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"設定裝置"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"裝置已連線"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"已連線到「%s」"</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"無法連線"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"無法連線"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"嘗試手動配對裝置"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"嘗試讓裝置進入配對模式"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"鄰近裝置"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"與你帳戶連結的裝置"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"你儲存的裝置已可使用"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"鄰近分享"</string>
+ <string name="common_devices" msgid="2635603125608104442">"裝置"</string>
+ <string name="common_connecting" msgid="160531481424245303">"連線中…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"電池電量:%d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"完成"</string>
<string name="paring_action_save" msgid="6259357442067880136">"儲存"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"連線"</string>
diff --git a/nearby/halfsheet/res/values-zu/strings.xml b/nearby/halfsheet/res/values-zu/strings.xml
index 33fb405..3f26469 100644
--- a/nearby/halfsheet/res/values-zu/strings.xml
+++ b/nearby/halfsheet/res/values-zu/strings.xml
@@ -20,7 +20,18 @@
<string name="fast_pair_setup_in_progress" msgid="4158762239172829807">"Iqalisa Ukusetha…"</string>
<string name="fast_pair_title_setup" msgid="2894360355540593246">"Setha idivayisi"</string>
<string name="fast_pair_device_ready" msgid="2903490346082833101">"Idivayisi ixhunyiwe"</string>
+ <string name="fast_pair_device_ready_with_device_name" msgid="2151967995692339422">"Ixhunywe ku-\"%s\""</string>
<string name="fast_pair_title_fail" msgid="5677174346601290232">"Ayikwazanga ukuxhuma"</string>
+ <string name="fast_pair_unable_to_connect" msgid="3661854812014294569">"Ayikwazanga ukuxhuma"</string>
+ <string name="fast_pair_unable_to_connect_description" msgid="3926830740860653891">"Zama ukubhangqa kule divayisi"</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" msgid="3197372738187738030">"Zama ukubeka le divayisi kumodi yokubhangqa"</string>
+ <string name="devices_within_reach_channel_name" msgid="876280551450910440">"Amadivayisi afinyelelekayo"</string>
+ <string name="devices_with_your_account_channel_name" msgid="8120067812798598102">"Amadivayisi ane-akhawunti yakho"</string>
+ <string name="fast_pair_your_device" msgid="3662423897069320840">"Idivayisi yakho elondoloziwe ikhona"</string>
+ <string name="common_nearby_title" msgid="5480324514713607015">"Eduze"</string>
+ <string name="common_devices" msgid="2635603125608104442">"Amadivayisi"</string>
+ <string name="common_connecting" msgid="160531481424245303">"Iyaxhuma…"</string>
+ <string name="common_battery_level" msgid="8748495823047456645">"Ibhethri: %d%%"</string>
<string name="paring_action_done" msgid="6888875159174470731">"Kwenziwe"</string>
<string name="paring_action_save" msgid="6259357442067880136">"Londoloza"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Xhuma"</string>
diff --git a/nearby/halfsheet/res/values/strings.xml b/nearby/halfsheet/res/values/strings.xml
index 01a82e4..c1f53d4 100644
--- a/nearby/halfsheet/res/values/strings.xml
+++ b/nearby/halfsheet/res/values/strings.xml
@@ -35,8 +35,22 @@
[CHAR LIMIT=30]
-->
<string name="fast_pair_device_ready">Device connected</string>
+ <string name="fast_pair_device_ready_with_device_name" description="Notification title combined with device name after we successfully pair with the audio device. For example: Connected to "Tommy's Bose QC35." [BACKUP_MESSAGE_ID: 6018442069058338390]">Connected to \u201c%s\u201d</string>
<!-- Title text shown when peripheral device fail to connect to phone. [CHAR_LIMIT=30] -->
<string name="fast_pair_title_fail">Couldn\'t connect</string>
+ <string name="fast_pair_unable_to_connect" description="Notification title after a pairing has failed. [CHAR LIMIT=30]">Unable to connect</string>
+ <string name="fast_pair_unable_to_connect_description" description="Notification body after a pairing has failed. [CHAR LIMIT=120]">Try manually pairing to the device</string>
+ <string name="fast_pair_turn_on_bt_device_pairing_mode" description="Notification body after a pairing has failed. [CHAR LIMIT=120]">Try putting the device into pairing mode</string>
+
+ <!--
+ ============================================================
+ PAIRING NOTIFICATION
+ ============================================================
+ -->
+
+ <string name="devices_within_reach_channel_name" description="Notification channel for devices within reach. [CHAR LIMIT=37]">Devices within reach</string>
+ <string name="devices_with_your_account_channel_name" description="Notification channel for devices that are connected to the user's account. [CHAR LIMIT=37]">Devices with your account</string>
+ <string name="fast_pair_your_device" description="Notification title for devices that are recognized as being owned by you. [CHAR LIMIT=30]">Your saved device is available</string>
<!--
============================================================
@@ -44,6 +58,14 @@
============================================================
-->
+ <!-- Title for Nearby component [CHAR LIMIT=40] -->
+ <string name="common_nearby_title">Nearby</string>
+ <!-- The product name for devices notification and list view. [CHAR LIMIT=37]-->
+ <string name="common_devices">Devices</string>
+ <!-- Text used to indicate that a connection attempt is ongoing [CHAR LIMIT=20] -->
+ <string name="common_connecting">Connecting…</string>
+ <!-- Label describing the battery level, for example "Battery: 72%". [CHAR LIMIT=60] -->
+ <string name="common_battery_level">Battery: %d%%</string>
<!--
A button shown after paring process to dismiss the current activity.
[CHAR LIMIT=30]
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
index 07e5776..94f4ef4 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
@@ -18,13 +18,19 @@
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_FAST_PAIR_HALF_SHEET_CANCEL;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_HALF_SHEET_FOREGROUND_STATE;
+import static com.android.nearby.halfsheet.constants.Constant.DEVICE_PAIRING_FRAGMENT_TYPE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_FOREGROUND;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_INFO;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_IS_RETROACTIVE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_TYPE;
+import static com.android.nearby.halfsheet.constants.Constant.TAG;
+import static com.android.nearby.halfsheet.constants.FastPairConstants.EXTRA_MODEL_ID;
+import static com.android.nearby.halfsheet.constants.UserActionHandlerBase.EXTRA_MAC_ADDRESS;
import static com.android.nearby.halfsheet.fragment.DevicePairingFragment.APP_LAUNCH_FRAGMENT_TYPE;
-import static com.android.server.nearby.common.bluetooth.fastpair.FastPairConstants.EXTRA_MODEL_ID;
-import static com.android.server.nearby.common.fastpair.service.UserActionHandlerBase.EXTRA_MAC_ADDRESS;
-import static com.android.server.nearby.fastpair.Constant.ACTION_FAST_PAIR_HALF_SHEET_CANCEL;
-import static com.android.server.nearby.fastpair.Constant.DEVICE_PAIRING_FRAGMENT_TYPE;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_INFO;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_TYPE;
import android.content.Intent;
import android.os.Bundle;
@@ -49,31 +55,6 @@
* A class show Fast Pair related information in Half sheet format.
*/
public class HalfSheetActivity extends FragmentActivity {
-
- public static final String TAG = "FastPairHalfSheet";
-
- public static final String EXTRA_HALF_SHEET_CONTENT =
- "com.android.nearby.halfsheet.HALF_SHEET_CONTENT";
- public static final String EXTRA_TITLE =
- "com.android.nearby.halfsheet.HALF_SHEET_TITLE";
- public static final String EXTRA_DESCRIPTION =
- "com.android.nearby.halfsheet.HALF_SHEET_DESCRIPTION";
- public static final String EXTRA_HALF_SHEET_ID =
- "com.android.nearby.halfsheet.HALF_SHEET_ID";
- public static final String EXTRA_HALF_SHEET_IS_RETROACTIVE =
- "com.android.nearby.halfsheet.HALF_SHEET_IS_RETROACTIVE";
- public static final String EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR =
- "com.android.nearby.halfsheet.HALF_SHEET_IS_SUBSEQUENT_PAIR";
- public static final String EXTRA_HALF_SHEET_PAIRING_RESURFACE =
- "com.android.nearby.halfsheet.EXTRA_HALF_SHEET_PAIRING_RESURFACE";
- public static final String ACTION_HALF_SHEET_FOREGROUND_STATE =
- "com.android.nearby.halfsheet.ACTION_HALF_SHEET_FOREGROUND_STATE";
- // Intent extra contains the user gmail name eg. testaccount@gmail.com.
- public static final String EXTRA_HALF_SHEET_ACCOUNT_NAME =
- "com.android.nearby.halfsheet.HALF_SHEET_ACCOUNT_NAME";
- public static final String EXTRA_HALF_SHEET_FOREGROUND =
- "com.android.nearby.halfsheet.EXTRA_HALF_SHEET_FOREGROUND";
- public static final String ARG_FRAGMENT_STATE = "ARG_FRAGMENT_STATE";
@Nullable
private HalfSheetModuleFragment mHalfSheetModuleFragment;
@Nullable
@@ -141,6 +122,10 @@
@Override
protected void onStart() {
super.onStart();
+ BroadcastUtils.sendBroadcast(
+ this,
+ new Intent(ACTION_HALF_SHEET_FOREGROUND_STATE)
+ .putExtra(EXTRA_HALF_SHEET_FOREGROUND, true));
}
@Override
@@ -207,30 +192,48 @@
finish();
}
+
+ /**
+ * Changes the half sheet ban state to active.
+ * Sometimes users leave half sheet to go to fast pair info page,
+ * we do not want the behavior to be counted as dismiss.
+ */
+ public void sendBanStateResetBroadcast() {
+ if (mScanFastPairStoreItem == null) {
+ return;
+ }
+ BroadcastUtils.sendBroadcast(
+ this,
+ new Intent(ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET)
+ .putExtra(EXTRA_MODEL_ID, mScanFastPairStoreItem.getModelId()
+ .toLowerCase(Locale.ROOT)));
+ }
+
private void sendHalfSheetCancelBroadcast() {
BroadcastUtils.sendBroadcast(
this,
new Intent(ACTION_HALF_SHEET_FOREGROUND_STATE)
.putExtra(EXTRA_HALF_SHEET_FOREGROUND, false));
- if (mScanFastPairStoreItem != null) {
- BroadcastUtils.sendBroadcast(
- this,
- new Intent(ACTION_FAST_PAIR_HALF_SHEET_CANCEL)
- .putExtra(EXTRA_MODEL_ID,
- mScanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT))
- .putExtra(EXTRA_HALF_SHEET_TYPE,
- getIntent().getStringExtra(EXTRA_HALF_SHEET_TYPE))
- .putExtra(
- EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR,
- getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR,
- false))
- .putExtra(
- EXTRA_HALF_SHEET_IS_RETROACTIVE,
- getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_RETROACTIVE,
- false))
- .putExtra(EXTRA_MAC_ADDRESS, mScanFastPairStoreItem.getAddress()),
- ACCESS_FINE_LOCATION);
+ if (mScanFastPairStoreItem == null) {
+ return;
}
+ BroadcastUtils.sendBroadcast(
+ this,
+ new Intent(ACTION_FAST_PAIR_HALF_SHEET_CANCEL)
+ .putExtra(EXTRA_MODEL_ID,
+ mScanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT))
+ .putExtra(EXTRA_HALF_SHEET_TYPE,
+ getIntent().getStringExtra(EXTRA_HALF_SHEET_TYPE))
+ .putExtra(
+ EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR,
+ getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR,
+ false))
+ .putExtra(
+ EXTRA_HALF_SHEET_IS_RETROACTIVE,
+ getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_RETROACTIVE,
+ false))
+ .putExtra(EXTRA_MAC_ADDRESS, mScanFastPairStoreItem.getAddress()),
+ ACCESS_FINE_LOCATION);
}
@Override
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/Constant.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/Constant.java
new file mode 100644
index 0000000..65c76d1
--- /dev/null
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/Constant.java
@@ -0,0 +1,65 @@
+/*
+ * 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 com.android.nearby.halfsheet.constants;
+
+/**
+ * String constant for half sheet.
+ */
+public class Constant {
+ public static final String TAG = "FastPairHalfSheet";
+ private static final String PREFIX = "com.android.nearby.halfsheet.";
+
+ // Intent extra
+ public static final String EXTRA_BINDER = "com.android.server.nearby.fastpair.BINDER";
+ public static final String EXTRA_BUNDLE = "com.android.server.nearby.fastpair.BUNDLE_EXTRA";
+
+ public static final String EXTRA_TITLE = PREFIX + "HALF_SHEET_TITLE";
+ public static final String EXTRA_DESCRIPTION = PREFIX + "HALF_SHEET_DESCRIPTION";
+ public static final String EXTRA_HALF_SHEET_ID = PREFIX + "HALF_SHEET_ID";
+ public static final String EXTRA_HALF_SHEET_INFO = PREFIX + "HALF_SHEET";
+ public static final String EXTRA_HALF_SHEET_TYPE = PREFIX + "HALF_SHEET_TYPE";
+ public static final String EXTRA_HALF_SHEET_ACCOUNT_NAME = PREFIX + "HALF_SHEET_ACCOUNT_NAME";
+ public static final String EXTRA_HALF_SHEET_CONTENT = PREFIX + "HALF_SHEET_CONTENT";
+ public static final String EXTRA_HALF_SHEET_FOREGROUND =
+ PREFIX + "EXTRA_HALF_SHEET_FOREGROUND";
+ public static final String EXTRA_HALF_SHEET_IS_RETROACTIVE =
+ PREFIX + "HALF_SHEET_IS_RETROACTIVE";
+ public static final String EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR =
+ PREFIX + "HALF_SHEET_IS_SUBSEQUENT_PAIR";
+ public static final String EXTRA_HALF_SHEET_PAIRING_RESURFACE =
+ PREFIX + "EXTRA_HALF_SHEET_PAIRING_RESURFACE";
+
+ // Intent Actions
+ public static final String ACTION_HALF_SHEET_FOREGROUND_STATE =
+ PREFIX + "ACTION_HALF_SHEET_FOREGROUND_STATE";
+ public static final String ACTION_FAST_PAIR_HALF_SHEET_CANCEL =
+ "com.android.nearby.ACTION_FAST_PAIR_HALF_SHEET_CANCEL";
+ public static final String ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET =
+ "com.android.nearby.ACTION_FAST_PAIR_BAN_STATE_RESET";
+ public static final String ACTION_RESOURCES_APK =
+ "android.nearby.SHOW_HALFSHEET";
+ public static final String ACTION_FAST_PAIR = PREFIX + "ACTION_MAGIC_PAIR";
+
+ public static final String RESULT_FAIL = "RESULT_FAIL";
+ public static final String ARG_FRAGMENT_STATE = "ARG_FRAGMENT_STATE";
+ public static final String DEVICE_PAIRING_FRAGMENT_TYPE = "DEVICE_PAIRING";
+
+ // Content url for help page about Fast Pair in half sheet.
+ // Todo(b/246007000): Add a flag to set up content url of the help page.
+ public static final String FAST_PAIR_HALF_SHEET_HELP_URL =
+ "https://support.google.com/android/answer/9075925";
+}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/FastPairConstants.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/FastPairConstants.java
new file mode 100644
index 0000000..7cfd33a
--- /dev/null
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/FastPairConstants.java
@@ -0,0 +1,26 @@
+/*
+ * 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 com.android.nearby.halfsheet.constants;
+
+/** Constants to share with other team. */
+public class FastPairConstants {
+ private static final String PACKAGE_NAME = "com.android.server.nearby";
+ public static final String PREFIX = PACKAGE_NAME + ".common.bluetooth.fastpair.";
+
+ /** MODEL_ID item name for extended intent field. */
+ public static final String EXTRA_MODEL_ID = PREFIX + "MODEL_ID";
+}
diff --git a/nearby/service/java/com/android/server/nearby/common/fastpair/service/UserActionHandlerBase.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/UserActionHandlerBase.java
similarity index 85%
rename from nearby/service/java/com/android/server/nearby/common/fastpair/service/UserActionHandlerBase.java
rename to nearby/halfsheet/src/com/android/nearby/halfsheet/constants/UserActionHandlerBase.java
index 67d87e3..767c6d6 100644
--- a/nearby/service/java/com/android/server/nearby/common/fastpair/service/UserActionHandlerBase.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/constants/UserActionHandlerBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.nearby.common.fastpair.service;
+package com.android.nearby.halfsheet.constants;
/** Handles intents to {@link com.android.server.nearby.fastpair.FastPairManager}. */
public class UserActionHandlerBase {
@@ -25,5 +25,5 @@
public static final String EXTRA_COMPANION_APP = ACTION_PREFIX + "EXTRA_COMPANION_APP";
public static final String EXTRA_MAC_ADDRESS = PREFIX + "EXTRA_MAC_ADDRESS";
+ public static final String ACTION_FAST_PAIR = ACTION_PREFIX + "ACTION_FAST_PAIR";
}
-
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java
index 320965b..9f5c915 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java
@@ -17,22 +17,24 @@
import static android.text.TextUtils.isEmpty;
-import static com.android.nearby.halfsheet.HalfSheetActivity.ARG_FRAGMENT_STATE;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_DESCRIPTION;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_HALF_SHEET_ACCOUNT_NAME;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_HALF_SHEET_CONTENT;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_HALF_SHEET_ID;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_TITLE;
-import static com.android.nearby.halfsheet.HalfSheetActivity.TAG;
+import static com.android.nearby.halfsheet.constants.Constant.ARG_FRAGMENT_STATE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_BINDER;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_BUNDLE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_DESCRIPTION;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_ACCOUNT_NAME;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_CONTENT;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_ID;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_INFO;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_TITLE;
+import static com.android.nearby.halfsheet.constants.Constant.FAST_PAIR_HALF_SHEET_HELP_URL;
+import static com.android.nearby.halfsheet.constants.Constant.RESULT_FAIL;
+import static com.android.nearby.halfsheet.constants.Constant.TAG;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.FAILED;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.FOUND_DEVICE;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.NOT_STARTED;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.PAIRED_LAUNCHABLE;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.PAIRED_UNLAUNCHABLE;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.PAIRING;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_BINDER;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_BUNDLE;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_INFO;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
@@ -61,6 +63,7 @@
import com.android.nearby.halfsheet.HalfSheetActivity;
import com.android.nearby.halfsheet.R;
import com.android.nearby.halfsheet.utils.FastPairUtils;
+import com.android.nearby.halfsheet.utils.HelpUtils;
import com.android.nearby.halfsheet.utils.IconUtils;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -183,6 +186,11 @@
new FastPairUiServiceClient(getContext(), mBundle.getBinder(EXTRA_BINDER));
mFastPairUiServiceClient.registerHalfSheetStateCallBack(this);
}
+ if (args.containsKey(EXTRA_HALF_SHEET_CONTENT)) {
+ if (RESULT_FAIL.equals(args.getString(EXTRA_HALF_SHEET_CONTENT))) {
+ mPairStatus = PairStatusMetadata.Status.FAIL;
+ }
+ }
if (args.containsKey(ARG_FRAGMENT_STATE)) {
mFragmentState = (HalfSheetFragmentState) args.getSerializable(ARG_FRAGMENT_STATE);
}
@@ -230,12 +238,12 @@
if (icon != null) {
mImage.setImageBitmap(icon);
}
- mConnectButton.setOnClickListener(v -> onConnectClick());
+ mConnectButton.setOnClickListener(v -> onConnectClicked());
mCancelButton.setOnClickListener(v ->
((HalfSheetActivity) getActivity()).onCancelClicked());
mSettingsButton.setOnClickListener(v -> onSettingsClicked());
- mSetupButton.setOnClickListener(v -> onSetupClick());
-
+ mSetupButton.setOnClickListener(v -> onSetupClicked());
+ mInfoIconButton.setOnClickListener(v -> onHelpClicked());
return rootView;
}
@@ -250,7 +258,14 @@
public void onStart() {
super.onStart();
Log.v(TAG, "onStart: invalidate states");
- invalidateState();
+ // If the fragmentState is not NOT_STARTED, it is because the fragment was just resumed from
+ // configuration change (e.g. rotating the screen or half-sheet resurface). Let's recover
+ // the UI directly.
+ if (mFragmentState != NOT_STARTED) {
+ setState(mFragmentState);
+ } else {
+ invalidateState();
+ }
}
@Override
@@ -266,7 +281,7 @@
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
}
- private void onSetupClick() {
+ private void onSetupClicked() {
String companionApp =
FastPairUtils.getCompanionAppFromActionUrl(mScanFastPairStoreItem.getActionUrl());
Intent intent =
@@ -284,7 +299,7 @@
}
}
- private void onConnectClick() {
+ private void onConnectClicked() {
if (mScanFastPairStoreItem == null) {
Log.w(TAG, "No pairing related information in half sheet");
return;
@@ -303,6 +318,12 @@
.build());
}
+ private void onHelpClicked() {
+ HelpUtils.showHelpPage(getContext(), FAST_PAIR_HALF_SHEET_HELP_URL);
+ ((HalfSheetActivity) getActivity()).sendBanStateResetBroadcast();
+ getActivity().finish();
+ }
+
// Receives callback from service.
@Override
public void onPairUpdate(FastPairDevice fastPairDevice, PairStatusMetadata pairStatusMetadata) {
@@ -475,8 +496,7 @@
case FAILED:
return mScanFastPairStoreItem.getFastPairStrings().getPairingFailDescription();
case PAIRED_UNLAUNCHABLE:
- getString(R.string.fast_pair_device_ready);
- // fall through
+ return getString(R.string.fast_pair_device_ready);
case FOUND_DEVICE:
case NOT_STARTED:
return mScanFastPairStoreItem.getFastPairStrings().getInitialPairingDescription();
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java
index f1db4d0..d87c015 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java
@@ -15,7 +15,7 @@
*/
package com.android.nearby.halfsheet.fragment;
-import static com.android.nearby.halfsheet.HalfSheetActivity.TAG;
+import static com.android.nearby.halfsheet.constants.Constant.TAG;
import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.NOT_STARTED;
import android.os.Bundle;
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java
index 00a365c..a1588a9 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java
@@ -15,8 +15,8 @@
*/
package com.android.nearby.halfsheet.utils;
-import static com.android.server.nearby.common.fastpair.service.UserActionHandlerBase.EXTRA_COMPANION_APP;
-import static com.android.server.nearby.fastpair.UserActionHandler.ACTION_FAST_PAIR;
+import static com.android.nearby.halfsheet.constants.UserActionHandlerBase.ACTION_FAST_PAIR;
+import static com.android.nearby.halfsheet.constants.UserActionHandlerBase.EXTRA_COMPANION_APP;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/HelpUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/HelpUtils.java
new file mode 100644
index 0000000..98f2242
--- /dev/null
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/HelpUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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 com.android.nearby.halfsheet.utils;
+
+import static com.android.nearby.halfsheet.constants.Constant.TAG;
+
+import static java.util.Objects.requireNonNull;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
+
+/**
+ * Util class for launching help page in Fast Pair.
+ */
+public class HelpUtils {
+ /**
+ * Sets up the info button to launch a help page
+ */
+ public static void showHelpPage(Context context, String url) {
+ requireNonNull(context, "context cannot be null");
+ requireNonNull(url, "url cannot be null");
+
+ try {
+ context.startActivity(createHelpPageIntent(url));
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Failed to find activity for url " + url, e);
+ }
+ }
+
+ /**
+ * Creates the intent for help page
+ */
+ private static Intent createHelpPageIntent(String url) {
+ return new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java
index 218c756..e547369 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java
@@ -16,17 +16,13 @@
package com.android.nearby.halfsheet.utils;
-import static com.android.nearby.halfsheet.HalfSheetActivity.TAG;
+import static com.android.nearby.halfsheet.constants.Constant.TAG;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
import android.util.Log;
import androidx.annotation.Nullable;
-import androidx.core.graphics.ColorUtils;
/**
* Utility class for icon size verification.
@@ -85,49 +81,12 @@
BitmapFactory.decodeByteArray(imageData, /* offset= */ 0, size);
if (IconUtils.isIconSizeCorrect(icon)) {
// Do not add background for Half Sheet.
- return IconUtils.addWhiteCircleBackground(icon);
+ return icon;
}
} catch (OutOfMemoryError e) {
Log.w(TAG, "getIcon: Failed to decode icon, returning null.", e);
}
return null;
}
-
- /** Adds a circular, white background to the bitmap. */
- @Nullable
- public static Bitmap addWhiteCircleBackground(Bitmap bitmap) {
- if (bitmap == null) {
- Log.w(TAG, "addWhiteCircleBackground: Bitmap is null, not adding background.");
- return null;
- }
-
- if (bitmap.getWidth() != bitmap.getHeight()) {
- Log.w(TAG, "addWhiteCircleBackground: Bitmap dimensions not square. Skipping"
- + "adding background.");
- return bitmap;
- }
-
- int padding = (int) (bitmap.getWidth() * NOTIFICATION_BACKGROUND_PADDING_PERCENT);
- Bitmap bitmapWithBackground =
- Bitmap.createBitmap(
- bitmap.getWidth() + (2 * padding),
- bitmap.getHeight() + (2 * padding),
- bitmap.getConfig());
- Canvas canvas = new Canvas(bitmapWithBackground);
- Paint paint = new Paint();
- paint.setColor(
- ColorUtils.setAlphaComponent(
- Color.WHITE, (int) (255 * NOTIFICATION_BACKGROUND_ALPHA)));
- paint.setStyle(Paint.Style.FILL);
- paint.setAntiAlias(true);
- canvas.drawCircle(
- bitmapWithBackground.getWidth() / 2,
- bitmapWithBackground.getHeight() / 2,
- bitmapWithBackground.getWidth() / 2,
- paint);
- canvas.drawBitmap(bitmap, padding, padding, null);
-
- return bitmapWithBackground;
- }
}
diff --git a/nearby/service/Android.bp b/nearby/service/Android.bp
index ef07bb9..d860048 100644
--- a/nearby/service/Android.bp
+++ b/nearby/service/Android.bp
@@ -24,23 +24,6 @@
],
}
-filegroup {
- name: "nearby-service-string-res",
- srcs: [
- "java/**/Constant.java",
- "java/**/UserActionHandlerBase.java",
- "java/**/UserActionHandler.java",
- "java/**/FastPairConstants.java",
- ],
-}
-
-java_library {
- name: "nearby-service-string",
- srcs: [":nearby-service-string-res"],
- libs: ["framework-bluetooth"],
- sdk_version: "module_current",
-}
-
// Common lib for nearby end-to-end testing.
java_library {
name: "nearby-common-lib",
@@ -90,6 +73,7 @@
"framework-configinfrastructure",
"framework-connectivity-t.impl",
"framework-statsd",
+ "HalfSheetUX",
],
static_libs: [
"androidx.core_core",
diff --git a/nearby/service/java/com/android/server/nearby/NearbyService.java b/nearby/service/java/com/android/server/nearby/NearbyService.java
index 0b12521..514de16 100644
--- a/nearby/service/java/com/android/server/nearby/NearbyService.java
+++ b/nearby/service/java/com/android/server/nearby/NearbyService.java
@@ -37,6 +37,7 @@
import android.nearby.IScanListener;
import android.nearby.NearbyManager;
import android.nearby.ScanRequest;
+import android.nearby.aidl.IOffloadCallback;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -144,6 +145,11 @@
mBroadcastProviderManager.stopBroadcast(listener);
}
+ @Override
+ public void queryOffloadCapability(IOffloadCallback callback) {
+
+ }
+
/**
* Called by the service initializer.
*
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java
index 0ff1bf2..008891f 100644
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java
+++ b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java
@@ -16,15 +16,12 @@
package com.android.server.nearby.common.bluetooth.fastpair;
+import static com.android.nearby.halfsheet.constants.FastPairConstants.PREFIX;
+
import android.bluetooth.BluetoothDevice;
/** Constants to share with other team. */
public class FastPairConstants {
- private static final String PACKAGE_NAME = "com.android.server.nearby";
- private static final String PREFIX = PACKAGE_NAME + ".common.bluetooth.fastpair.";
-
- /** MODEL_ID item name for extended intent field. */
- public static final String EXTRA_MODEL_ID = PREFIX + "MODEL_ID";
/** CONNECTION_ID item name for extended intent field. */
public static final String EXTRA_CONNECTION_ID = PREFIX + "CONNECTION_ID";
/** BLUETOOTH_MAC_ADDRESS item name for extended intent field. */
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/Constant.java b/nearby/service/java/com/android/server/nearby/fastpair/Constant.java
index 0695b5f..f35703f 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/Constant.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/Constant.java
@@ -30,14 +30,4 @@
* Tag for Fast Pair service related logs.
*/
public static final String TAG = "FastPairService";
-
- public static final String EXTRA_BINDER = "com.android.server.nearby.fastpair.BINDER";
- public static final String EXTRA_BUNDLE = "com.android.server.nearby.fastpair.BUNDLE_EXTRA";
- public static final String ACTION_FAST_PAIR_HALF_SHEET_CANCEL =
- "com.android.nearby.ACTION_FAST_PAIR_HALF_SHEET_CANCEL";
- public static final String EXTRA_HALF_SHEET_INFO =
- "com.android.nearby.halfsheet.HALF_SHEET";
- public static final String EXTRA_HALF_SHEET_TYPE =
- "com.android.nearby.halfsheet.HALF_SHEET_TYPE";
- public static final String DEVICE_PAIRING_FRAGMENT_TYPE = "DEVICE_PAIRING";
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
index d459329..412b738 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
@@ -31,9 +31,14 @@
import com.android.server.nearby.common.ble.decode.FastPairDecoder;
import com.android.server.nearby.common.ble.util.RangingUtils;
import com.android.server.nearby.common.bloomfilter.BloomFilter;
+import com.android.server.nearby.common.bloomfilter.FastPairBloomFilterHasher;
import com.android.server.nearby.common.locator.Locator;
+import com.android.server.nearby.fastpair.cache.DiscoveryItem;
+import com.android.server.nearby.fastpair.cache.FastPairCacheManager;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
+import com.android.server.nearby.fastpair.notification.FastPairNotificationManager;
import com.android.server.nearby.provider.FastPairDataProvider;
+import com.android.server.nearby.util.ArrayUtils;
import com.android.server.nearby.util.DataUtils;
import com.android.server.nearby.util.Hex;
@@ -49,10 +54,18 @@
public class FastPairAdvHandler {
Context mContext;
String mBleAddress;
- // Need to be deleted after notification manager in use.
- private boolean mIsFirst = false;
+ // TODO(b/247152236): Need to confirm the usage
+ // and deleted this after notification manager in use.
+ private boolean mIsFirst = true;
private FastPairDataProvider mPairDataProvider;
private static final double NEARBY_DISTANCE_THRESHOLD = 0.6;
+ // The byte, 0bLLLLTTTT, for battery length and type.
+ // Bit 0 - 3: type, 0b0011 (show UI indication) or 0b0100 (hide UI indication).
+ // Bit 4 - 7: length.
+ // https://developers.google.com/nearby/fast-pair/specifications/extensions/batterynotification
+ private static final byte SHOW_UI_INDICATION = 0b0011;
+ private static final byte HIDE_UI_INDICATION = 0b0100;
+ private static final int LENGTH_ADVERTISEMENT_TYPE_BIT = 4;
/** The types about how the bloomfilter is processed. */
public enum ProcessBloomFilterType {
@@ -91,7 +104,7 @@
if (FastPairDecoder.checkModelId(fastPairDevice.getData())) {
byte[] model = FastPairDecoder.getModelId(fastPairDevice.getData());
- Log.d(TAG, "On discovery model id " + Hex.bytesToStringLowercase(model));
+ Log.v(TAG, "On discovery model id " + Hex.bytesToStringLowercase(model));
// Use api to get anti spoofing key from model id.
try {
List<Account> accountList = mPairDataProvider.loadFastPairEligibleAccounts();
@@ -111,7 +124,7 @@
}
Locator.get(mContext, FastPairHalfSheetManager.class).showHalfSheet(
DataUtils.toScanFastPairStoreItem(
- response, mBleAddress,
+ response, mBleAddress, Hex.bytesToStringLowercase(model),
accountList.isEmpty() ? null : accountList.get(0).name));
} catch (IllegalStateException e) {
Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
@@ -119,43 +132,176 @@
} else {
// Start to process bloom filter. Yet to finish.
try {
- List<Account> accountList = mPairDataProvider.loadFastPairEligibleAccounts();
- byte[] bloomFilterByteArray = FastPairDecoder
- .getBloomFilter(fastPairDevice.getData());
- byte[] bloomFilterSalt = FastPairDecoder
- .getBloomFilterSalt(fastPairDevice.getData());
- if (bloomFilterByteArray == null || bloomFilterByteArray.length == 0) {
- return;
- }
+ subsequentPair(fastPairDevice);
} catch (IllegalStateException e) {
- Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
+ Log.e(TAG, "handleBroadcast: subsequent pair failed", e);
}
}
}
+ @Nullable
+ @VisibleForTesting
+ static byte[] getBloomFilterBytes(byte[] data) {
+ byte[] bloomFilterBytes = FastPairDecoder.getBloomFilter(data);
+ if (bloomFilterBytes == null) {
+ bloomFilterBytes = FastPairDecoder.getBloomFilterNoNotification(data);
+ }
+ if (ArrayUtils.isEmpty(bloomFilterBytes)) {
+ Log.d(TAG, "subsequentPair: bloomFilterByteArray empty");
+ return null;
+ }
+ return bloomFilterBytes;
+ }
+
+ private int getTxPower(FastPairDevice scannedDevice,
+ Data.FastPairDeviceWithAccountKey recognizedDevice) {
+ return recognizedDevice.getDiscoveryItem().getTxPower() == 0
+ ? scannedDevice.getTxPower()
+ : recognizedDevice.getDiscoveryItem().getTxPower();
+ }
+
+ private void subsequentPair(FastPairDevice scannedDevice) {
+ byte[] data = scannedDevice.getData();
+
+ if (ArrayUtils.isEmpty(data)) {
+ Log.d(TAG, "subsequentPair: no valid data");
+ return;
+ }
+
+ byte[] bloomFilterBytes = getBloomFilterBytes(data);
+ if (ArrayUtils.isEmpty(bloomFilterBytes)) {
+ Log.d(TAG, "subsequentPair: no valid bloom filter");
+ return;
+ }
+
+ byte[] salt = FastPairDecoder.getBloomFilterSalt(data);
+ if (ArrayUtils.isEmpty(salt)) {
+ Log.d(TAG, "subsequentPair: no valid salt");
+ return;
+ }
+ byte[] saltWithData = concat(salt, generateBatteryData(data));
+
+ List<Account> accountList = mPairDataProvider.loadFastPairEligibleAccounts();
+ for (Account account : accountList) {
+ List<Data.FastPairDeviceWithAccountKey> devices =
+ mPairDataProvider.loadFastPairDeviceWithAccountKey(account);
+ Data.FastPairDeviceWithAccountKey recognizedDevice =
+ findRecognizedDevice(devices,
+ new BloomFilter(bloomFilterBytes,
+ new FastPairBloomFilterHasher()), saltWithData);
+ if (recognizedDevice == null) {
+ Log.v(TAG, "subsequentPair: recognizedDevice is null");
+ continue;
+ }
+
+ // Check the distance of the device if the distance is larger than the
+ // threshold
+ if (!isNearby(scannedDevice.getRssi(), getTxPower(scannedDevice, recognizedDevice))) {
+ Log.v(TAG,
+ "subsequentPair: the distance of the device is larger than the threshold");
+ return;
+ }
+
+ // Check if the device is already paired
+ List<Cache.StoredFastPairItem> storedFastPairItemList =
+ Locator.get(mContext, FastPairCacheManager.class)
+ .getAllSavedStoredFastPairItem();
+ Cache.StoredFastPairItem recognizedStoredFastPairItem =
+ findRecognizedDeviceFromCachedItem(storedFastPairItemList,
+ new BloomFilter(bloomFilterBytes,
+ new FastPairBloomFilterHasher()), saltWithData);
+ if (recognizedStoredFastPairItem != null) {
+ // The bloomfilter is recognized in the cache so the device is paired
+ // before
+ Log.d(TAG, "bloom filter is recognized in the cache");
+ continue;
+ }
+ showSubsequentNotification(account, scannedDevice, recognizedDevice);
+ }
+ }
+
+ private void showSubsequentNotification(Account account, FastPairDevice scannedDevice,
+ Data.FastPairDeviceWithAccountKey recognizedDevice) {
+ // Get full info from api the initial request will only return
+ // part of the info due to size limit.
+ List<Data.FastPairDeviceWithAccountKey> devicesWithAccountKeys =
+ mPairDataProvider.loadFastPairDeviceWithAccountKey(account,
+ List.of(recognizedDevice.getAccountKey().toByteArray()));
+ if (devicesWithAccountKeys == null || devicesWithAccountKeys.isEmpty()) {
+ Log.d(TAG, "No fast pair device with account key is found.");
+ return;
+ }
+
+ // Saved device from footprint does not have ble address.
+ // We need to fill ble address with current scan result.
+ Cache.StoredDiscoveryItem storedDiscoveryItem =
+ devicesWithAccountKeys.get(0).getDiscoveryItem().toBuilder()
+ .setMacAddress(
+ scannedDevice.getBluetoothAddress())
+ .build();
+ // Show notification
+ FastPairNotificationManager fastPairNotificationManager =
+ Locator.get(mContext, FastPairNotificationManager.class);
+ DiscoveryItem item = new DiscoveryItem(mContext, storedDiscoveryItem);
+ Locator.get(mContext, FastPairCacheManager.class).saveDiscoveryItem(item);
+ fastPairNotificationManager.showDiscoveryNotification(item,
+ devicesWithAccountKeys.get(0).getAccountKey().toByteArray());
+ }
+
+ // Battery advertisement format:
+ // Byte 0: Battery length and type, Bit 0 - 3: type, Bit 4 - 7: length.
+ // Byte 1 - 3: Battery values.
+ // Reference:
+ // https://developers.google.com/nearby/fast-pair/specifications/extensions/batterynotification
+ @VisibleForTesting
+ static byte[] generateBatteryData(byte[] data) {
+ byte[] batteryLevelNoNotification = FastPairDecoder.getBatteryLevelNoNotification(data);
+ boolean suppressBatteryNotification =
+ (batteryLevelNoNotification != null && batteryLevelNoNotification.length > 0);
+ byte[] batteryValues =
+ suppressBatteryNotification
+ ? batteryLevelNoNotification
+ : FastPairDecoder.getBatteryLevel(data);
+ if (ArrayUtils.isEmpty(batteryValues)) {
+ return new byte[0];
+ }
+ return generateBatteryData(suppressBatteryNotification, batteryValues);
+ }
+
+ @VisibleForTesting
+ static byte[] generateBatteryData(boolean suppressBatteryNotification, byte[] batteryValues) {
+ return concat(
+ new byte[] {
+ (byte)
+ (batteryValues.length << LENGTH_ADVERTISEMENT_TYPE_BIT
+ | (suppressBatteryNotification
+ ? HIDE_UI_INDICATION : SHOW_UI_INDICATION))
+ },
+ batteryValues);
+ }
+
/**
* Checks the bloom filter to see if any of the devices are recognized and should have a
* notification displayed for them. A device is recognized if the account key + salt combination
* is inside the bloom filter.
*/
@Nullable
+ @VisibleForTesting
static Data.FastPairDeviceWithAccountKey findRecognizedDevice(
List<Data.FastPairDeviceWithAccountKey> devices, BloomFilter bloomFilter, byte[] salt) {
- Log.d(TAG, "saved devices size in the account is " + devices.size());
for (Data.FastPairDeviceWithAccountKey device : devices) {
if (device.getAccountKey().toByteArray() == null || salt == null) {
return null;
}
byte[] rotatedKey = concat(device.getAccountKey().toByteArray(), salt);
+
StringBuilder sb = new StringBuilder();
for (byte b : rotatedKey) {
sb.append(b);
}
+
if (bloomFilter.possiblyContains(rotatedKey)) {
- Log.d(TAG, "match " + sb.toString());
return device;
- } else {
- Log.d(TAG, "not match " + sb.toString());
}
}
return null;
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
index e1db7e5..447d199 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
@@ -129,11 +129,8 @@
Log.d(TAG, "Incorrect state, ignore pairing");
return;
}
- boolean useLargeNotifications =
- item.getAuthenticationPublicKeySecp256R1() != null;
FastPairNotificationManager fastPairNotificationManager =
- new FastPairNotificationManager(mContext, item,
- useLargeNotifications);
+ Locator.get(mContext, FastPairNotificationManager.class);
FastPairHalfSheetManager fastPairHalfSheetManager =
Locator.get(mContext, FastPairHalfSheetManager.class);
mFastPairCacheManager.saveDiscoveryItem(item);
@@ -169,7 +166,7 @@
@Nullable byte[] accountKey,
@Nullable String companionApp) {
FastPairNotificationManager fastPairNotificationManager =
- new FastPairNotificationManager(mContext, item, false);
+ Locator.get(mContext, FastPairNotificationManager.class);
FastPairHalfSheetManager fastPairHalfSheetManager =
Locator.get(mContext, FastPairHalfSheetManager.class);
PairingProgressHandlerBase pairingProgressHandlerBase =
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
index e3de4e2..8a9614e 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
@@ -16,8 +16,16 @@
package com.android.server.nearby.fastpair;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_FAST_PAIR;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_FAST_PAIR_HALF_SHEET_CANCEL;
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_HALF_SHEET_FOREGROUND_STATE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_FOREGROUND;
+import static com.android.nearby.halfsheet.constants.FastPairConstants.EXTRA_MODEL_ID;
import static com.android.server.nearby.fastpair.Constant.TAG;
+import static com.google.common.io.BaseEncoding.base16;
+
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.app.KeyguardManager;
@@ -25,7 +33,6 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -35,8 +42,6 @@
import android.nearby.NearbyManager;
import android.nearby.ScanCallback;
import android.nearby.ScanRequest;
-import android.net.Uri;
-import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -89,7 +94,6 @@
/** A notification ID which should be dismissed */
public static final String EXTRA_NOTIFICATION_ID = ACTION_PREFIX + "EXTRA_NOTIFICATION_ID";
- public static final String ACTION_RESOURCES_APK = "android.nearby.SHOW_HALFSHEET";
private static Executor sFastPairExecutor;
@@ -98,17 +102,74 @@
final LocatorContextWrapper mLocatorContextWrapper;
final IntentFilter mIntentFilter;
final Locator mLocator;
- private boolean mScanEnabled;
+ private boolean mScanEnabled = false;
+ private final FastPairCacheManager mFastPairCacheManager;
private final BroadcastReceiver mScreenBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)
- || intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
- Log.d(TAG, "onReceive: ACTION_SCREEN_ON or boot complete.");
- invalidateScan();
- } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
- processBluetoothConnectionEvent(intent);
+ String action = intent.getAction();
+ switch (action) {
+ case Intent.ACTION_SCREEN_ON:
+ Log.d(TAG, "onReceive: ACTION_SCREEN_ON");
+ invalidateScan();
+ break;
+ case Intent.ACTION_BOOT_COMPLETED:
+ Log.d(TAG, "onReceive: ACTION_BOOT_COMPLETED.");
+ invalidateScan();
+ break;
+ case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
+ Log.d(TAG, "onReceive: ACTION_BOND_STATE_CHANGED");
+ processBluetoothConnectionEvent(intent);
+ break;
+ case ACTION_HALF_SHEET_FOREGROUND_STATE:
+ boolean state = intent.getBooleanExtra(EXTRA_HALF_SHEET_FOREGROUND, false);
+ Log.d(TAG, "halfsheet report foreground state: " + state);
+ Locator.get(mLocatorContextWrapper, FastPairHalfSheetManager.class)
+ .setHalfSheetForeground(state);
+ break;
+ case ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET:
+ Log.d(TAG, "onReceive: ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET");
+ String deviceModelId = intent.getStringExtra(EXTRA_MODEL_ID);
+ if (deviceModelId == null) {
+ Log.d(TAG, "HalfSheetManager reset device ban state skipped, "
+ + "deviceModelId not found");
+ break;
+ }
+ Locator.get(mLocatorContextWrapper, FastPairHalfSheetManager.class)
+ .resetBanState(deviceModelId);
+ break;
+ case ACTION_FAST_PAIR_HALF_SHEET_CANCEL:
+ Log.d(TAG, "onReceive: ACTION_FAST_PAIR_HALF_SHEET_CANCEL");
+ String modelId = intent.getStringExtra(EXTRA_MODEL_ID);
+ if (modelId == null) {
+ Log.d(TAG, "skip half sheet cancel action, model id not found");
+ break;
+ }
+ Locator.get(mLocatorContextWrapper, FastPairHalfSheetManager.class)
+ .dismiss(modelId);
+ break;
+ case ACTION_FAST_PAIR:
+ Log.d(TAG, "onReceive: ACTION_FAST_PAIR");
+ String itemId = intent.getStringExtra(UserActionHandler.EXTRA_ITEM_ID);
+ String accountKeyString = intent
+ .getStringExtra(UserActionHandler.EXTRA_FAST_PAIR_SECRET);
+ if (itemId == null || accountKeyString == null) {
+ Log.d(TAG, "skip pair action, item id "
+ + "or fast pair account key not found");
+ break;
+ }
+ try {
+ FastPairController controller =
+ Locator.getFromContextWrapper(mLocatorContextWrapper,
+ FastPairController.class);
+ if (mFastPairCacheManager != null) {
+ controller.pair(mFastPairCacheManager.getDiscoveryItem(itemId),
+ base16().decode(accountKeyString), /* companionApp= */ null);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Cannot find FastPairController class", e);
+ }
}
}
};
@@ -120,6 +181,8 @@
mLocator.bind(new FastPairModule());
Rpcs.GetObservedDeviceResponse getObservedDeviceResponse =
Rpcs.GetObservedDeviceResponse.newBuilder().build();
+ mFastPairCacheManager =
+ Locator.getFromContextWrapper(mLocatorContextWrapper, FastPairCacheManager.class);
}
final ScanCallback mScanCallback = new ScanCallback() {
@@ -141,6 +204,11 @@
byte[] modelArray = FastPairDecoder.getModelId(fastPairDevice.getData());
Log.d(TAG, "lost model id" + Hex.bytesToStringLowercase(modelArray));
}
+
+ @Override
+ public void onError(int errorCode) {
+ Log.w(TAG, "[FastPairManager] Scan error is " + errorCode);
+ }
};
/**
@@ -151,14 +219,13 @@
mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
mIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ mIntentFilter.addAction(ACTION_FAST_PAIR_HALF_SHEET_CANCEL);
+ mIntentFilter.addAction(ACTION_FAST_PAIR_HALF_SHEET_BAN_STATE_RESET);
+ mIntentFilter.addAction(ACTION_HALF_SHEET_FOREGROUND_STATE);
+ mIntentFilter.addAction(ACTION_FAST_PAIR);
- mLocatorContextWrapper.getContext()
- .registerReceiver(mScreenBroadcastReceiver, mIntentFilter);
-
- Locator.getFromContextWrapper(mLocatorContextWrapper, FastPairCacheManager.class);
- // Default false for now.
- mScanEnabled = NearbyManager.getFastPairScanEnabled(mLocatorContextWrapper.getContext());
- registerFastPairScanChangeContentObserver(mLocatorContextWrapper.getContentResolver());
+ mLocatorContextWrapper.getContext().registerReceiver(mScreenBroadcastReceiver,
+ mIntentFilter, Context.RECEIVER_EXPORTED);
}
/**
@@ -259,6 +326,13 @@
context, item.getMacAddress(),
prefsBuilder.build(),
null);
+ connection.setOnPairedCallback(
+ address -> {
+ Log.v(TAG, "connection on paired callback;");
+ // TODO(b/259150992) add fill Bluetooth metadata values logic
+ pairingProgressHandlerBase.onPairedCallbackCalled(
+ connection, accountKey, footprints, address);
+ });
pairingProgressHandlerBase.onPairingSetupCompleted();
FastPairConnection.SharedSecret sharedSecret;
@@ -353,25 +427,6 @@
}
}
- private void registerFastPairScanChangeContentObserver(ContentResolver resolver) {
- mFastPairScanChangeContentObserver = new ContentObserver(ForegroundThread.getHandler()) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- super.onChange(selfChange, uri);
- setScanEnabled(
- NearbyManager.getFastPairScanEnabled(mLocatorContextWrapper.getContext()));
- }
- };
- try {
- resolver.registerContentObserver(
- Settings.Secure.getUriFor(NearbyManager.FAST_PAIR_SCAN_ENABLED),
- /* notifyForDescendants= */ false,
- mFastPairScanChangeContentObserver);
- } catch (SecurityException e) {
- Log.e(TAG, "Failed to register content observer for fast pair scan.", e);
- }
- }
-
/**
* Processed task in a background thread
*/
@@ -399,13 +454,6 @@
return (NearbyManager) mLocatorContextWrapper
.getApplicationContext().getSystemService(Context.NEARBY_SERVICE);
}
- private void setScanEnabled(boolean scanEnabled) {
- if (mScanEnabled == scanEnabled) {
- return;
- }
- mScanEnabled = scanEnabled;
- invalidateScan();
- }
/**
* Starts or stops scanning according to mAllowScan value.
@@ -414,7 +462,7 @@
NearbyManager nearbyManager = getNearbyManager();
if (nearbyManager == null) {
Log.w(TAG, "invalidateScan: "
- + "failed to start or stop scannning because NearbyManager is null.");
+ + "failed to start or stop scanning because NearbyManager is null.");
return;
}
if (mScanEnabled) {
@@ -444,8 +492,7 @@
processBackgroundTask(new Runnable() {
@Override
public void run() {
- mLocatorContextWrapper.getLocator().get(FastPairCacheManager.class)
- .removeStoredFastPairItem(device.getAddress());
+ mFastPairCacheManager.removeStoredFastPairItem(device.getAddress());
}
});
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairModule.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairModule.java
index d7946d1..1df4723 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairModule.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairModule.java
@@ -24,6 +24,7 @@
import com.android.server.nearby.fastpair.cache.FastPairCacheManager;
import com.android.server.nearby.fastpair.footprint.FootprintsDeviceManager;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
+import com.android.server.nearby.fastpair.notification.FastPairNotificationManager;
import java.time.Clock;
import java.time.Instant;
@@ -52,6 +53,9 @@
locator.bind(FastPairHalfSheetManager.class, new FastPairHalfSheetManager(context));
} else if (type.equals(FastPairAdvHandler.class)) {
locator.bind(FastPairAdvHandler.class, new FastPairAdvHandler(context));
+ } else if (type.equals(FastPairNotificationManager.class)) {
+ locator.bind(FastPairNotificationManager.class,
+ new FastPairNotificationManager(context));
} else if (type.equals(Clock.class)) {
locator.bind(Clock.class, new Clock() {
@Override
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/HalfSheetResources.java b/nearby/service/java/com/android/server/nearby/fastpair/HalfSheetResources.java
new file mode 100644
index 0000000..86dd44d
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/HalfSheetResources.java
@@ -0,0 +1,129 @@
+/*
+ * 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 com.android.server.nearby.fastpair;
+
+import static com.android.server.nearby.fastpair.Constant.TAG;
+
+import android.annotation.ColorInt;
+import android.annotation.ColorRes;
+import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Utility to obtain the {@link com.android.nearby.halfsheet} {@link Resources}, in the
+ * HalfSheetUX APK.
+ * @hide
+ */
+public class HalfSheetResources {
+ @NonNull
+ private final Context mContext;
+
+ @Nullable
+ private Context mResourcesContext = null;
+
+ @Nullable
+ private static Context sTestResourcesContext = null;
+
+ public HalfSheetResources(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Convenience method to mock all resources for the duration of a test.
+ *
+ * Call with a null context to reset after the test.
+ */
+ @VisibleForTesting
+ public static void setResourcesContextForTest(@Nullable Context testContext) {
+ sTestResourcesContext = testContext;
+ }
+
+ /**
+ * Get the {@link Context} of the resources package.
+ */
+ @Nullable
+ public synchronized Context getResourcesContext() {
+ if (sTestResourcesContext != null) {
+ return sTestResourcesContext;
+ }
+
+ if (mResourcesContext != null) {
+ return mResourcesContext;
+ }
+
+ String packageName = PackageUtils.getHalfSheetApkPkgName(mContext);
+ if (packageName == null) {
+ Log.e(TAG, "Resolved package not found");
+ return null;
+ }
+ final Context pkgContext;
+ try {
+ pkgContext = mContext.createPackageContext(packageName, 0 /* flags */);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Resolved package not found");
+ return null;
+ }
+
+ mResourcesContext = pkgContext;
+ return pkgContext;
+ }
+
+ /**
+ * Get the {@link Resources} of the ServiceConnectivityResources APK.
+ */
+ public Resources get() {
+ return getResourcesContext().getResources();
+ }
+
+ /**
+ * Gets the {@code String} with given resource Id.
+ */
+ public String getString(@StringRes int id) {
+ return get().getString(id);
+ }
+
+ /**
+ * Gets the {@code String} with given resource Id and formatted arguments.
+ */
+ public String getString(@StringRes int id, Object... formatArgs) {
+ return get().getString(id, formatArgs);
+ }
+
+ /**
+ * Gets the {@link Drawable} with given resource Id.
+ */
+ public Drawable getDrawable(@DrawableRes int id) {
+ return get().getDrawable(id, getResourcesContext().getTheme());
+ }
+
+ /**
+ * Gets a themed color integer associated with a particular resource ID.
+ */
+ @ColorInt
+ public int getColor(@ColorRes int id) {
+ return get().getColor(id, getResourcesContext().getTheme());
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/PackageUtils.java b/nearby/service/java/com/android/server/nearby/fastpair/PackageUtils.java
new file mode 100644
index 0000000..0ff8caf
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/PackageUtils.java
@@ -0,0 +1,72 @@
+/*
+ * 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 com.android.server.nearby.fastpair;
+
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_RESOURCES_APK;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.util.Log;
+
+import com.android.server.nearby.util.Environment;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Helper class for package related methods.
+ */
+public class PackageUtils {
+
+ /**
+ * Gets the package name of HalfSheet.apk
+ */
+ @Nullable
+ public static String getHalfSheetApkPkgName(Context context) {
+ List<ResolveInfo> resolveInfos = context
+ .getPackageManager().queryIntentActivities(
+ new Intent(ACTION_RESOURCES_APK),
+ PackageManager.MATCH_SYSTEM_ONLY);
+
+ // remove apps that don't live in the nearby apex
+ resolveInfos.removeIf(info ->
+ !Environment.isAppInNearbyApex(info.activityInfo.applicationInfo));
+
+ if (resolveInfos.isEmpty()) {
+ // Resource APK not loaded yet, print a stack trace to see where this is called from
+ Log.e("FastPairManager", "Attempted to fetch resources before halfsheet "
+ + " APK is installed or package manager can't resolve correctly!",
+ new IllegalStateException());
+ return null;
+ }
+
+ if (resolveInfos.size() > 1) {
+ // multiple apps found, log a warning, but continue
+ Log.w("FastPairManager", "Found > 1 APK that can resolve halfsheet APK intent: "
+ + resolveInfos.stream()
+ .map(info -> info.activityInfo.applicationInfo.packageName)
+ .collect(Collectors.joining(", ")));
+ }
+
+ // Assume the first ResolveInfo is the one we're looking for
+ ResolveInfo info = resolveInfos.get(0);
+ return info.activityInfo.applicationInfo.packageName;
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/UserActionHandler.java b/nearby/service/java/com/android/server/nearby/fastpair/UserActionHandler.java
index 674633d..2b00ca5 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/UserActionHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/UserActionHandler.java
@@ -16,16 +16,16 @@
package com.android.server.nearby.fastpair;
-import com.android.server.nearby.common.fastpair.service.UserActionHandlerBase;
+import com.android.nearby.halfsheet.constants.UserActionHandlerBase;
/**
* User action handler class.
*/
public class UserActionHandler extends UserActionHandlerBase {
- public static final String EXTRA_DISCOVERY_ITEM = PREFIX + "EXTRA_DISCOVERY_ITEM";
+ public static final String EXTRA_ITEM_ID = PREFIX + "EXTRA_DISCOVERY_ITEM";
public static final String EXTRA_FAST_PAIR_SECRET = PREFIX + "EXTRA_FAST_PAIR_SECRET";
- public static final String ACTION_FAST_PAIR = ACTION_PREFIX + "ACTION_FAST_PAIR";
+
public static final String EXTRA_PRIVATE_BLE_ADDRESS =
ACTION_PREFIX + "EXTRA_PRIVATE_BLE_ADDRESS";
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/blocklist/Blocklist.java b/nearby/service/java/com/android/server/nearby/fastpair/blocklist/Blocklist.java
new file mode 100644
index 0000000..d8091ba
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/blocklist/Blocklist.java
@@ -0,0 +1,66 @@
+/*
+ * 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 com.android.server.nearby.fastpair.blocklist;
+
+
+/**
+ * Skeletal implementation of Blocklist
+ *
+ * <p>Controls the frequency to show the available device to users.
+ */
+public interface Blocklist {
+
+ /** Checks certain item is blocked within durationSeconds. */
+ boolean isBlocklisted(int id, int durationSeconds);
+
+ /** Updates the HalfSheet blocklist state for a given id. */
+ boolean updateState(int id, BlocklistState state);
+
+ /** Removes the HalfSheet blocklist. */
+ boolean removeBlocklist(int id);
+
+ /** Resets certain device ban state to active. */
+ void resetBlockState(int id);
+
+ /**
+ * Used for indicate what state is the blocklist item.
+ *
+ * <p>The different states have differing priorities and higher priority states will override
+ * lower one.
+ * More details and state transition diagram,
+ * see: https://docs.google.com/document/d/1wzE5CHXTkzKJY-2AltSrxOVteom2Nebc1sbjw1Tt7BQ/edit?usp=sharing&resourcekey=0-L-wUz3Hw5gZPThm5VPwHOQ
+ */
+ enum BlocklistState {
+ UNKNOWN(0),
+ ACTIVE(1),
+ DISMISSED(2),
+ PAIRING(3),
+ PAIRED(4),
+ DO_NOT_SHOW_AGAIN(5),
+ DO_NOT_SHOW_AGAIN_LONG(6);
+
+ private final int mValue;
+
+ BlocklistState(final int value) {
+ this.mValue = value;
+ }
+
+ public boolean hasHigherPriorityThan(BlocklistState otherState) {
+ return this.mValue > otherState.mValue;
+ }
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/blocklist/BlocklistElement.java b/nearby/service/java/com/android/server/nearby/fastpair/blocklist/BlocklistElement.java
new file mode 100644
index 0000000..d058d58
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/blocklist/BlocklistElement.java
@@ -0,0 +1,39 @@
+/*
+ * 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 com.android.server.nearby.fastpair.blocklist;
+
+import com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState;
+import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetBlocklist;
+
+/** Element in the {@link FastPairHalfSheetBlocklist} */
+public class BlocklistElement {
+ private final long mTimeStamp;
+ private final BlocklistState mState;
+
+ public BlocklistElement(BlocklistState state, long timeStamp) {
+ this.mState = state;
+ this.mTimeStamp = timeStamp;
+ }
+
+ public Long getTimeStamp() {
+ return mTimeStamp;
+ }
+
+ public BlocklistState getState() {
+ return mState;
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetBlocklist.java b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetBlocklist.java
new file mode 100644
index 0000000..146b97a
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetBlocklist.java
@@ -0,0 +1,193 @@
+/*
+ * 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 com.android.server.nearby.fastpair.halfsheet;
+
+
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.ACTIVE;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.DISMISSED;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN_LONG;
+
+import android.util.Log;
+import android.util.LruCache;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.server.nearby.fastpair.blocklist.Blocklist;
+import com.android.server.nearby.fastpair.blocklist.BlocklistElement;
+import com.android.server.nearby.util.Clock;
+import com.android.server.nearby.util.DefaultClock;
+
+
+/**
+ * Maintains a list of half sheet id to tell whether the half sheet should be suppressed or not.
+ *
+ * <p>When user cancel half sheet, the ble address related half sheet should be in block list and
+ * after certain duration of time half sheet can show again.
+ */
+public class FastPairHalfSheetBlocklist extends LruCache<Integer, BlocklistElement>
+ implements Blocklist {
+ private static final String TAG = "HalfSheetBlocklist";
+ // Number of entries in the FastPair blocklist
+ private static final int FAST_PAIR_BLOCKLIST_CACHE_SIZE = 16;
+ // Duration between first half sheet dismiss and second half sheet shows: 2 seconds
+ private static final int FAST_PAIR_HALF_SHEET_DISMISS_COOL_DOWN_MILLIS = 2000;
+ // The timeout to ban half sheet after user trigger the ban logic even number of time : 1 day
+ private static final int DURATION_RESURFACE_HALFSHEET_EVEN_NUMBER_BAN_MILLI_SECONDS = 86400000;
+ // Timeout for DISMISSED entries in the blocklist to expire : 1 min
+ private static final int FAST_PAIR_BLOCKLIST_DISMISSED_HALF_SHEET_TIMEOUT_MILLIS = 60000;
+ // The timeout for entries in the blocklist to expire : 1 day
+ private static final int STATE_EXPIRATION_MILLI_SECONDS = 86400000;
+ private long mEndTimeBanAllItems;
+ private final Clock mClock;
+
+
+ public FastPairHalfSheetBlocklist() {
+ // Reuses the size limit from notification cache.
+ // Number of entries in the FastPair blocklist
+ super(FAST_PAIR_BLOCKLIST_CACHE_SIZE);
+ mClock = new DefaultClock();
+ }
+
+ @VisibleForTesting
+ FastPairHalfSheetBlocklist(int size, Clock clock) {
+ super(size);
+ mClock = clock;
+ }
+
+ /**
+ * Checks whether need to show HalfSheet or not.
+ *
+ * <p> When the HalfSheet {@link BlocklistState} is DISMISS, there is a little cool down period
+ * to allow half sheet to reshow.
+ * If the HalfSheet {@link BlocklistState} is DO_NOT_SHOW_AGAIN, within durationMilliSeconds
+ * from banned start time, the function will return true
+ * otherwise it will return false if the status is expired
+ * If the HalfSheet {@link BlocklistState} is DO_NOT_SHOW_AGAIN_LONG, the half sheet will be
+ * baned for a longer duration.
+ *
+ * @param id {@link com.android.nearby.halfsheet.HalfSheetActivity} id
+ * @param durationMilliSeconds the time duration from item is banned to now
+ * @return whether the HalfSheet is blocked to show
+ */
+ @Override
+ public boolean isBlocklisted(int id, int durationMilliSeconds) {
+ if (shouldBanAllItem()) {
+ return true;
+ }
+ BlocklistElement entry = get(id);
+ if (entry == null) {
+ return false;
+ }
+ if (entry.getState().equals(DO_NOT_SHOW_AGAIN)) {
+ Log.d(TAG, "BlocklistState: DO_NOT_SHOW_AGAIN");
+ return mClock.elapsedRealtime() < entry.getTimeStamp() + durationMilliSeconds;
+ }
+ if (entry.getState().equals(DO_NOT_SHOW_AGAIN_LONG)) {
+ Log.d(TAG, "BlocklistState: DO_NOT_SHOW_AGAIN_LONG ");
+ return mClock.elapsedRealtime()
+ < entry.getTimeStamp()
+ + DURATION_RESURFACE_HALFSHEET_EVEN_NUMBER_BAN_MILLI_SECONDS;
+ }
+
+ if (entry.getState().equals(ACTIVE)) {
+ Log.d(TAG, "BlocklistState: ACTIVE");
+ return false;
+ }
+ // Get some cool down period for dismiss state
+ if (entry.getState().equals(DISMISSED)) {
+ Log.d(TAG, "BlocklistState: DISMISSED");
+ return mClock.elapsedRealtime()
+ < entry.getTimeStamp() + FAST_PAIR_HALF_SHEET_DISMISS_COOL_DOWN_MILLIS;
+ }
+ if (dismissStateHasExpired(entry)) {
+ Log.d(TAG, "stateHasExpired: True");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeBlocklist(int id) {
+ BlocklistElement oldValue = remove(id);
+ return oldValue != null;
+ }
+
+ /**
+ * Updates the HalfSheet blocklist state
+ *
+ * <p>When the new {@link BlocklistState} has higher priority then old {@link BlocklistState} or
+ * the old {@link BlocklistState} status is expired,the function will update the status.
+ *
+ * @param id HalfSheet id
+ * @param state Blocklist state
+ * @return update status successful or not
+ */
+ @Override
+ public boolean updateState(int id, BlocklistState state) {
+ BlocklistElement entry = get(id);
+ if (entry == null || state.hasHigherPriorityThan(entry.getState())
+ || dismissStateHasExpired(entry)) {
+ Log.d(TAG, "updateState: " + state);
+ put(id, new BlocklistElement(state, mClock.elapsedRealtime()));
+ return true;
+ }
+ return false;
+ }
+
+ /** Enables lower state to override the higher value state. */
+ public void forceUpdateState(int id, BlocklistState state) {
+ put(id, new BlocklistElement(state, mClock.elapsedRealtime()));
+ }
+
+ /** Resets certain device ban state to active. */
+ @Override
+ public void resetBlockState(int id) {
+ BlocklistElement entry = get(id);
+ if (entry != null) {
+ put(id, new BlocklistElement(ACTIVE, mClock.elapsedRealtime()));
+ }
+ }
+
+ /** Checks whether certain device state has expired. */
+ public boolean isStateExpired(int id) {
+ BlocklistElement entry = get(id);
+ if (entry != null) {
+ return mClock.elapsedRealtime() > entry.getTimeStamp() + STATE_EXPIRATION_MILLI_SECONDS;
+ }
+ return false;
+ }
+
+ private boolean dismissStateHasExpired(BlocklistElement entry) {
+ return mClock.elapsedRealtime()
+ > entry.getTimeStamp() + FAST_PAIR_BLOCKLIST_DISMISSED_HALF_SHEET_TIMEOUT_MILLIS;
+ }
+
+ /**
+ * Updates the end time that all half sheet will be banned.
+ */
+ void banAllItem(long banDurationTimeMillis) {
+ long endTime = mClock.elapsedRealtime() + banDurationTimeMillis;
+ if (endTime > mEndTimeBanAllItems) {
+ mEndTimeBanAllItems = endTime;
+ }
+ }
+
+ private boolean shouldBanAllItem() {
+ return mClock.elapsedRealtime() < mEndTimeBanAllItems;
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java
index 553d5ce..7b266a7 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java
@@ -16,34 +16,51 @@
package com.android.server.nearby.fastpair.halfsheet;
-import static com.android.server.nearby.fastpair.Constant.DEVICE_PAIRING_FRAGMENT_TYPE;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_BINDER;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_BUNDLE;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_INFO;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_TYPE;
-import static com.android.server.nearby.fastpair.FastPairManager.ACTION_RESOURCES_APK;
+import static com.android.nearby.halfsheet.constants.Constant.DEVICE_PAIRING_FRAGMENT_TYPE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_BINDER;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_BUNDLE;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_CONTENT;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_INFO;
+import static com.android.nearby.halfsheet.constants.Constant.EXTRA_HALF_SHEET_TYPE;
+import static com.android.nearby.halfsheet.constants.Constant.FAST_PAIR_HALF_SHEET_HELP_URL;
+import static com.android.nearby.halfsheet.constants.Constant.RESULT_FAIL;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.annotation.UiThread;
+import android.app.ActivityManager;
+import android.app.KeyguardManager;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.nearby.FastPairDevice;
import android.nearby.FastPairStatusCallback;
import android.nearby.PairStatusMetadata;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
+import android.util.LruCache;
+import android.widget.Toast;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.nearby.halfsheet.R;
+import com.android.server.nearby.common.eventloop.Annotations;
+import com.android.server.nearby.common.eventloop.EventLoop;
+import com.android.server.nearby.common.eventloop.NamedRunnable;
+import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
import com.android.server.nearby.fastpair.FastPairController;
+import com.android.server.nearby.fastpair.PackageUtils;
+import com.android.server.nearby.fastpair.blocklist.Blocklist;
import com.android.server.nearby.fastpair.cache.DiscoveryItem;
-import com.android.server.nearby.util.Environment;
+import java.util.HashMap;
import java.util.List;
-import java.util.stream.Collectors;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import service.proto.Cache;
@@ -55,20 +72,56 @@
private static final String HALF_SHEET_CLASS_NAME =
"com.android.nearby.halfsheet.HalfSheetActivity";
private static final String TAG = "FPHalfSheetManager";
+ public static final String FINISHED_STATE = "FINISHED_STATE";
+ @VisibleForTesting static final String DISMISS_HALFSHEET_RUNNABLE_NAME = "DismissHalfSheet";
+ @VisibleForTesting static final String SHOW_TOAST_RUNNABLE_NAME = "SuccessPairingToast";
+
+ // The timeout to ban half sheet after user trigger the ban logic odd number of time: 5 mins
+ private static final int DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS = 300000;
+ // Number of seconds half sheet will show after the advertisement is no longer seen.
+ private static final int HALF_SHEET_TIME_OUT_SECONDS = 12;
+
+ static final int HALFSHEET_ID_SEED = "new_fast_pair_half_sheet".hashCode();
private String mHalfSheetApkPkgName;
+ private boolean mIsHalfSheetForeground = false;
+ private boolean mIsActivePairing = false;
+ private Cache.ScanFastPairStoreItem mCurrentScanFastPairStoreItem = null;
private final LocatorContextWrapper mLocatorContextWrapper;
+ private final AtomicInteger mNotificationIds = new AtomicInteger(HALFSHEET_ID_SEED);
+ private FastPairHalfSheetBlocklist mHalfSheetBlocklist;
+ // Todo: Make "16" a flag, which can be updated from the server side.
+ final LruCache<String, Integer> mModelIdMap = new LruCache<>(16);
+ HalfSheetDismissState mHalfSheetDismissState = HalfSheetDismissState.ACTIVE;
+ // Ban count map track the number of ban happens to certain model id
+ // If the model id is baned by the odd number of time it is banned for 5 mins
+ // if the model id is banned even number of time ban 24 hours.
+ private final Map<Integer, Integer> mBanCountMap = new HashMap<>();
FastPairUiServiceImpl mFastPairUiService;
+ private NamedRunnable mDismissRunnable;
+
+ /**
+ * Half sheet state default is active. If user dismiss half sheet once controller will mark half
+ * sheet as dismiss state. If user dismiss half sheet twice controller will mark half sheet as
+ * ban state for certain period of time.
+ */
+ enum HalfSheetDismissState {
+ ACTIVE,
+ DISMISS,
+ BAN
+ }
public FastPairHalfSheetManager(Context context) {
this(new LocatorContextWrapper(context));
+ mHalfSheetBlocklist = new FastPairHalfSheetBlocklist();
}
@VisibleForTesting
- FastPairHalfSheetManager(LocatorContextWrapper locatorContextWrapper) {
+ public FastPairHalfSheetManager(LocatorContextWrapper locatorContextWrapper) {
mLocatorContextWrapper = locatorContextWrapper;
mFastPairUiService = new FastPairUiServiceImpl();
+ mHalfSheetBlocklist = new FastPairHalfSheetBlocklist();
}
/**
@@ -76,6 +129,40 @@
* app can't get the correct component name.
*/
public void showHalfSheet(Cache.ScanFastPairStoreItem scanFastPairStoreItem) {
+ String modelId = scanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT);
+ if (modelId == null) {
+ Log.d(TAG, "model id not found");
+ return;
+ }
+
+ synchronized (mModelIdMap) {
+ if (mModelIdMap.get(modelId) == null) {
+ mModelIdMap.put(modelId, createNewHalfSheetId());
+ }
+ }
+ int halfSheetId = mModelIdMap.get(modelId);
+
+ if (!allowedToShowHalfSheet(halfSheetId)) {
+ Log.d(TAG, "Not allow to show initial Half sheet");
+ return;
+ }
+
+ // If currently half sheet UI is in the foreground,
+ // DO NOT request start-activity to avoid unnecessary memory usage
+ if (mIsHalfSheetForeground) {
+ updateForegroundHalfSheet(scanFastPairStoreItem);
+ return;
+ } else {
+ // If the half sheet is not in foreground but the system is still pairing
+ // with the same device, mark as duplicate request and skip.
+ if (mCurrentScanFastPairStoreItem != null && mIsActivePairing
+ && mCurrentScanFastPairStoreItem.getAddress().toLowerCase(Locale.ROOT)
+ .equals(scanFastPairStoreItem.getAddress().toLowerCase(Locale.ROOT))) {
+ Log.d(TAG, "Same device is pairing.");
+ return;
+ }
+ }
+
try {
if (mLocatorContextWrapper != null) {
String packageName = getHalfSheetApkPkgName();
@@ -97,32 +184,78 @@
.setComponent(new ComponentName(packageName,
HALF_SHEET_CLASS_NAME)),
UserHandle.CURRENT);
+ mHalfSheetBlocklist.updateState(halfSheetId, Blocklist.BlocklistState.ACTIVE);
}
} catch (IllegalStateException e) {
Log.e(TAG, "Can't resolve package that contains half sheet");
}
+ Log.d(TAG, "show initial half sheet.");
+ mCurrentScanFastPairStoreItem = scanFastPairStoreItem;
+ mIsHalfSheetForeground = true;
+ enableAutoDismiss(scanFastPairStoreItem.getAddress(), HALF_SHEET_TIME_OUT_SECONDS);
}
/**
- * Shows pairing fail half sheet.
+ * Auto dismiss half sheet after timeout
*/
- public void showPairingFailed() {
- FastPairStatusCallback pairStatusCallback = mFastPairUiService.getPairStatusCallback();
- if (pairStatusCallback != null) {
- Log.v(TAG, "showPairingFailed: pairStatusCallback not NULL");
- pairStatusCallback.onPairUpdate(new FastPairDevice.Builder().build(),
- new PairStatusMetadata(PairStatusMetadata.Status.FAIL));
- } else {
- Log.w(TAG, "FastPairHalfSheetManager failed to show success half sheet because "
- + "the pairStatusCallback is null");
+ @VisibleForTesting
+ void enableAutoDismiss(String address, long timeoutDuration) {
+ if (mDismissRunnable == null
+ || !mDismissRunnable.name.equals(DISMISS_HALFSHEET_RUNNABLE_NAME)) {
+ mDismissRunnable =
+ new NamedRunnable(DISMISS_HALFSHEET_RUNNABLE_NAME) {
+ @Override
+ public void run() {
+ Log.d(TAG, "Dismiss the half sheet after "
+ + timeoutDuration + " seconds");
+ // BMW car kit will advertise even after pairing start,
+ // to avoid the half sheet be dismissed during active pairing,
+ // If the half sheet is in the pairing state, disable the auto dismiss.
+ // See b/182396106
+ if (mIsActivePairing) {
+ return;
+ }
+ mIsHalfSheetForeground = false;
+ FastPairStatusCallback pairStatusCallback =
+ mFastPairUiService.getPairStatusCallback();
+ if (pairStatusCallback != null) {
+ pairStatusCallback.onPairUpdate(new FastPairDevice.Builder()
+ .setBluetoothAddress(address).build(),
+ new PairStatusMetadata(PairStatusMetadata.Status.DISMISS));
+ } else {
+ Log.w(TAG, "pairStatusCallback is null,"
+ + " failed to enable auto dismiss ");
+ }
+ }
+ };
}
+ if (Locator.get(mLocatorContextWrapper, EventLoop.class).isPosted(mDismissRunnable)) {
+ disableDismissRunnable();
+ }
+ Locator.get(mLocatorContextWrapper, EventLoop.class)
+ .postRunnableDelayed(mDismissRunnable, SECONDS.toMillis(timeoutDuration));
}
- /**
- * Get the half sheet status whether it is foreground or dismissed
- */
- public boolean getHalfSheetForegroundState() {
- return true;
+ private void updateForegroundHalfSheet(Cache.ScanFastPairStoreItem scanFastPairStoreItem) {
+ if (mCurrentScanFastPairStoreItem == null) {
+ return;
+ }
+ if (mCurrentScanFastPairStoreItem.getAddress().toLowerCase(Locale.ROOT)
+ .equals(scanFastPairStoreItem.getAddress().toLowerCase(Locale.ROOT))) {
+ // If current address is the same, reset the timeout.
+ Log.d(TAG, "same Address device, reset the auto dismiss timeout");
+ enableAutoDismiss(scanFastPairStoreItem.getAddress(), HALF_SHEET_TIME_OUT_SECONDS);
+ } else {
+ // If current address is different, not reset timeout
+ // wait for half sheet auto dismiss or manually dismiss to start new pair.
+ if (mCurrentScanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT)
+ .equals(scanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT))) {
+ Log.d(TAG, "same model id device is also nearby");
+ }
+ Log.d(TAG, "showInitialHalfsheet: address changed, from "
+ + mCurrentScanFastPairStoreItem.getAddress()
+ + " to " + scanFastPairStoreItem.getAddress());
+ }
}
/**
@@ -140,23 +273,187 @@
/**
* Shows pairing success info.
+ * If the half sheet is not shown, show toast to remind user.
*/
public void showPairingSuccessHalfSheet(String address) {
- FastPairStatusCallback pairStatusCallback = mFastPairUiService.getPairStatusCallback();
- if (pairStatusCallback != null) {
+ resetPairingStateDisableAutoDismiss();
+ if (mIsHalfSheetForeground) {
+ FastPairStatusCallback pairStatusCallback = mFastPairUiService.getPairStatusCallback();
+ if (pairStatusCallback == null) {
+ Log.w(TAG, "FastPairHalfSheetManager failed to show success half sheet because "
+ + "the pairStatusCallback is null");
+ return;
+ }
+ Log.d(TAG, "showPairingSuccess: pairStatusCallback not NULL");
pairStatusCallback.onPairUpdate(
new FastPairDevice.Builder().setBluetoothAddress(address).build(),
new PairStatusMetadata(PairStatusMetadata.Status.SUCCESS));
} else {
- Log.w(TAG, "FastPairHalfSheetManager failed to show success half sheet because "
- + "the pairStatusCallback is null");
+ Locator.get(mLocatorContextWrapper, EventLoop.class)
+ .postRunnable(
+ new NamedRunnable(SHOW_TOAST_RUNNABLE_NAME) {
+ @Override
+ public void run() {
+ try {
+ Toast.makeText(mLocatorContextWrapper,
+ mLocatorContextWrapper
+ .getPackageManager()
+ .getResourcesForApplication(
+ getHalfSheetApkPkgName())
+ .getString(R.string.fast_pair_device_ready),
+ Toast.LENGTH_LONG).show();
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.d(TAG, "showPairingSuccess fail:"
+ + " package name cannot be found ");
+ e.printStackTrace();
+ }
+ }
+ });
}
}
/**
- * Removes dismiss runnable.
+ * Shows pairing fail half sheet.
+ * If the half sheet is not shown, create a new half sheet to help user go to Setting
+ * to manually pair with the device.
+ */
+ public void showPairingFailed() {
+ resetPairingStateDisableAutoDismiss();
+ if (mCurrentScanFastPairStoreItem == null) {
+ return;
+ }
+ if (mIsHalfSheetForeground) {
+ FastPairStatusCallback pairStatusCallback = mFastPairUiService.getPairStatusCallback();
+ if (pairStatusCallback != null) {
+ Log.v(TAG, "showPairingFailed: pairStatusCallback not NULL");
+ pairStatusCallback.onPairUpdate(
+ new FastPairDevice.Builder()
+ .setBluetoothAddress(mCurrentScanFastPairStoreItem.getAddress())
+ .build(),
+ new PairStatusMetadata(PairStatusMetadata.Status.FAIL));
+ } else {
+ Log.w(TAG, "FastPairHalfSheetManager failed to show fail half sheet because "
+ + "the pairStatusCallback is null");
+ }
+ } else {
+ String packageName = getHalfSheetApkPkgName();
+ if (packageName == null) {
+ Log.e(TAG, "package name is null");
+ return;
+ }
+ Bundle bundle = new Bundle();
+ bundle.putBinder(EXTRA_BINDER, mFastPairUiService);
+ mLocatorContextWrapper
+ .startActivityAsUser(new Intent(ACTIVITY_INTENT_ACTION)
+ .putExtra(EXTRA_HALF_SHEET_INFO,
+ mCurrentScanFastPairStoreItem.toByteArray())
+ .putExtra(EXTRA_HALF_SHEET_TYPE,
+ DEVICE_PAIRING_FRAGMENT_TYPE)
+ .putExtra(EXTRA_HALF_SHEET_CONTENT, RESULT_FAIL)
+ .putExtra(EXTRA_BUNDLE, bundle)
+ .setComponent(new ComponentName(packageName,
+ HALF_SHEET_CLASS_NAME)),
+ UserHandle.CURRENT);
+ Log.d(TAG, "Starts a new half sheet to showPairingFailed");
+ String modelId = mCurrentScanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT);
+ if (modelId == null || mModelIdMap.get(modelId) == null) {
+ Log.d(TAG, "info not enough");
+ return;
+ }
+ int halfSheetId = mModelIdMap.get(modelId);
+ mHalfSheetBlocklist.updateState(halfSheetId, Blocklist.BlocklistState.ACTIVE);
+ }
+ }
+
+ /**
+ * Removes dismiss half sheet runnable. When half sheet shows, there is timer for half sheet to
+ * dismiss. But when user is pairing, half sheet should not dismiss.
+ * So this function disable the runnable.
*/
public void disableDismissRunnable() {
+ if (mDismissRunnable == null) {
+ return;
+ }
+ Log.d(TAG, "remove dismiss runnable");
+ Locator.get(mLocatorContextWrapper, EventLoop.class).removeRunnable(mDismissRunnable);
+ }
+
+ /**
+ * When user first click back button or click the empty space in half sheet the half sheet will
+ * be banned for certain short period of time for that device model id. When user click cancel
+ * or dismiss half sheet for the second time the half sheet related item should be added to
+ * blocklist so the half sheet will not show again to interrupt user.
+ *
+ * @param modelId half sheet display item modelId.
+ */
+ @Annotations.EventThread
+ public void dismiss(String modelId) {
+ Log.d(TAG, "HalfSheetManager report dismiss device modelId: " + modelId);
+ mIsHalfSheetForeground = false;
+ Integer halfSheetId = mModelIdMap.get(modelId);
+ if (mDismissRunnable != null
+ && Locator.get(mLocatorContextWrapper, EventLoop.class)
+ .isPosted(mDismissRunnable)) {
+ disableDismissRunnable();
+ }
+ if (halfSheetId != null) {
+ Log.d(TAG, "id: " + halfSheetId + " half sheet is dismissed");
+ boolean isDontShowAgain =
+ !mHalfSheetBlocklist.updateState(halfSheetId,
+ Blocklist.BlocklistState.DISMISSED);
+ if (isDontShowAgain) {
+ if (!mBanCountMap.containsKey(halfSheetId)) {
+ mBanCountMap.put(halfSheetId, 0);
+ }
+ int dismissCountTrack = mBanCountMap.get(halfSheetId) + 1;
+ mBanCountMap.put(halfSheetId, dismissCountTrack);
+ if (dismissCountTrack % 2 == 1) {
+ Log.d(TAG, "id: " + halfSheetId + " half sheet is short time banned");
+ mHalfSheetBlocklist.forceUpdateState(halfSheetId,
+ Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN);
+ } else {
+ Log.d(TAG, "id: " + halfSheetId + " half sheet is long time banned");
+ mHalfSheetBlocklist.updateState(halfSheetId,
+ Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN_LONG);
+ }
+ }
+ }
+ }
+
+ /**
+ * Changes the half sheet ban state to active.
+ */
+ @UiThread
+ public void resetBanState(String modelId) {
+ Log.d(TAG, "HalfSheetManager reset device ban state modelId: " + modelId);
+ Integer halfSheetId = mModelIdMap.get(modelId);
+ if (halfSheetId == null) {
+ Log.d(TAG, "halfSheetId not found.");
+ return;
+ }
+ mHalfSheetBlocklist.resetBlockState(halfSheetId);
+ }
+
+ // Invokes this method to reset some states when showing the pairing result.
+ private void resetPairingStateDisableAutoDismiss() {
+ mIsActivePairing = false;
+ if (mDismissRunnable != null && Locator.get(mLocatorContextWrapper, EventLoop.class)
+ .isPosted(mDismissRunnable)) {
+ disableDismissRunnable();
+ }
+ }
+
+ /**
+ * When the device pairing finished should remove the suppression for the model id
+ * so the user canntry twice if the user want to.
+ */
+ public void reportDonePairing(int halfSheetId) {
+ mHalfSheetBlocklist.removeBlocklist(halfSheetId);
+ }
+
+ @VisibleForTesting
+ public FastPairHalfSheetBlocklist getHalfSheetBlocklist() {
+ return mHalfSheetBlocklist;
}
/**
@@ -166,9 +463,96 @@
}
/**
- * Notify manager the pairing has finished.
+ * Notifies manager the pairing has finished.
*/
public void notifyPairingProcessDone(boolean success, String address, DiscoveryItem item) {
+ mCurrentScanFastPairStoreItem = null;
+ mIsHalfSheetForeground = false;
+ }
+
+ private boolean allowedToShowHalfSheet(int halfSheetId) {
+ // Half Sheet will not show when the screen is locked so disable half sheet
+ KeyguardManager keyguardManager =
+ mLocatorContextWrapper.getSystemService(KeyguardManager.class);
+ if (keyguardManager != null && keyguardManager.isKeyguardLocked()) {
+ Log.d(TAG, "device is locked");
+ return false;
+ }
+
+ // Check whether the blocklist state has expired
+ if (mHalfSheetBlocklist.isStateExpired(halfSheetId)) {
+ mHalfSheetBlocklist.removeBlocklist(halfSheetId);
+ mBanCountMap.remove(halfSheetId);
+ }
+
+ // Half Sheet will not show when the model id is banned
+ if (mHalfSheetBlocklist.isBlocklisted(
+ halfSheetId, DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)) {
+ Log.d(TAG, "id: " + halfSheetId + " is blocked");
+ return false;
+ }
+ return !isHelpPageForeground();
+ }
+
+ /**
+ * Checks if the user already open the info page, return true to suppress half sheet.
+ * ActivityManager#getRunningTasks to get the most recent task and check the baseIntent's
+ * url to see if we should suppress half sheet.
+ */
+ private boolean isHelpPageForeground() {
+ ActivityManager activityManager =
+ mLocatorContextWrapper.getSystemService(ActivityManager.class);
+ if (activityManager == null) {
+ Log.d(TAG, "ActivityManager is null");
+ return false;
+ }
+ try {
+ List<ActivityManager.RunningTaskInfo> taskInfos = activityManager.getRunningTasks(1);
+ if (taskInfos.isEmpty()) {
+ Log.d(TAG, "Empty running tasks");
+ return false;
+ }
+ String url = taskInfos.get(0).baseIntent.getDataString();
+ Log.d(TAG, "Info page url:" + url);
+ if (FAST_PAIR_HALF_SHEET_HELP_URL.equals(url)) {
+ return true;
+ }
+ } catch (SecurityException e) {
+ Log.d(TAG, "Unable to get running tasks");
+ }
+ return false;
+ }
+
+ /** Report actively pairing when the Fast Pair starts. */
+ public void reportActivelyPairing() {
+ mIsActivePairing = true;
+ }
+
+
+ private Integer createNewHalfSheetId() {
+ return mNotificationIds.getAndIncrement();
+ }
+
+ /** Gets the half sheet status whether it is foreground or dismissed */
+ public boolean getHalfSheetForeground() {
+ return mIsHalfSheetForeground;
+ }
+
+ /** Sets whether the half sheet is at the foreground or not. */
+ public void setHalfSheetForeground(boolean state) {
+ mIsHalfSheetForeground = state;
+ }
+
+ /** Returns whether the fast pair is actively pairing . */
+ @VisibleForTesting
+ public boolean isActivePairing() {
+ return mIsActivePairing;
+ }
+
+ /** Sets fast pair to be active pairing or not, used for testing. */
+ @VisibleForTesting
+ public void setIsActivePairing(boolean isActivePairing) {
+ mIsActivePairing = isActivePairing;
}
/**
@@ -176,39 +560,12 @@
* getHalfSheetApkPkgName may invoke PackageManager multiple times and it does not have
* race condition check. Since there is no lock for mHalfSheetApkPkgName.
*/
- String getHalfSheetApkPkgName() {
+ private String getHalfSheetApkPkgName() {
if (mHalfSheetApkPkgName != null) {
return mHalfSheetApkPkgName;
}
- List<ResolveInfo> resolveInfos = mLocatorContextWrapper
- .getPackageManager().queryIntentActivities(
- new Intent(ACTION_RESOURCES_APK),
- PackageManager.MATCH_SYSTEM_ONLY);
-
- // remove apps that don't live in the nearby apex
- resolveInfos.removeIf(info ->
- !Environment.isAppInNearbyApex(info.activityInfo.applicationInfo));
-
- if (resolveInfos.isEmpty()) {
- // Resource APK not loaded yet, print a stack trace to see where this is called from
- Log.e("FastPairManager", "Attempted to fetch resources before halfsheet "
- + " APK is installed or package manager can't resolve correctly!",
- new IllegalStateException());
- return null;
- }
-
- if (resolveInfos.size() > 1) {
- // multiple apps found, log a warning, but continue
- Log.w("FastPairManager", "Found > 1 APK that can resolve halfsheet APK intent: "
- + resolveInfos.stream()
- .map(info -> info.activityInfo.applicationInfo.packageName)
- .collect(Collectors.joining(", ")));
- }
-
- // Assume the first ResolveInfo is the one we're looking for
- ResolveInfo info = resolveInfos.get(0);
- mHalfSheetApkPkgName = info.activityInfo.applicationInfo.packageName;
- Log.i("FastPairManager", "Found halfsheet APK at: " + mHalfSheetApkPkgName);
+ mHalfSheetApkPkgName = PackageUtils.getHalfSheetApkPkgName(mLocatorContextWrapper);
+ Log.v(TAG, "Found halfsheet APK at: " + mHalfSheetApkPkgName);
return mHalfSheetApkPkgName;
}
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairUiServiceImpl.java b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairUiServiceImpl.java
index 3bd273e..eb1fb85 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairUiServiceImpl.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairUiServiceImpl.java
@@ -27,6 +27,7 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.nearby.fastpair.FastPairController;
/**
@@ -93,6 +94,14 @@
}
/**
+ * Sets fastPairStatusCallback.
+ */
+ @VisibleForTesting
+ public void setFastPairStatusCallback(FastPairStatusCallback fastPairStatusCallback) {
+ mFastPairStatusCallback = fastPairStatusCallback;
+ }
+
+ /**
* Sets function for Fast Pair controller.
*/
public void setFastPairController(FastPairController fastPairController) {
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationBuilder.java b/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationBuilder.java
new file mode 100644
index 0000000..4260235
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationBuilder.java
@@ -0,0 +1,67 @@
+/*
+ * 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 com.android.server.nearby.fastpair.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.nearby.halfsheet.R;
+import com.android.server.nearby.fastpair.HalfSheetResources;
+import com.android.server.nearby.fastpair.PackageUtils;
+
+/** Wrapper class for Fast Pair specific logic for notification builder. */
+public class FastPairNotificationBuilder extends Notification.Builder {
+
+ @VisibleForTesting
+ static final String NOTIFICATION_OVERRIDE_NAME_EXTRA = "android.substName";
+ final String mPackageName;
+ final Context mContext;
+ final HalfSheetResources mResources;
+
+ public FastPairNotificationBuilder(Context context, String channelId) {
+ super(context, channelId);
+ this.mContext = context;
+ this.mPackageName = PackageUtils.getHalfSheetApkPkgName(context);
+ this.mResources = new HalfSheetResources(context);
+ }
+
+ /**
+ * If the flag is enabled, all the devices notification should use "Devices" as the source name,
+ * and links/Apps uses "Nearby". If the flag is not enabled, all notifications use "Nearby" as
+ * source name.
+ */
+ public FastPairNotificationBuilder setIsDevice(boolean isDevice) {
+ Bundle extras = new Bundle();
+ String notificationOverrideName =
+ isDevice
+ ? mResources.get().getString(R.string.common_devices)
+ : mResources.get().getString(R.string.common_nearby_title);
+ extras.putString(NOTIFICATION_OVERRIDE_NAME_EXTRA, notificationOverrideName);
+ addExtras(extras);
+ return this;
+ }
+
+ /** Set the "ticker" text which is sent to accessibility services. */
+ public FastPairNotificationBuilder setTickerForAccessibility(String tickerText) {
+ // On Lollipop and above, setTicker() tells Accessibility what to say about the notification
+ // (e.g. this is what gets announced when a HUN appears).
+ setTicker(tickerText);
+ return this;
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationManager.java b/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationManager.java
index b1ae573..c74249c 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotificationManager.java
@@ -16,51 +16,166 @@
package com.android.server.nearby.fastpair.notification;
+import static com.android.server.nearby.fastpair.Constant.TAG;
import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.NotificationManager;
import android.content.Context;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.nearby.halfsheet.R;
+import com.android.server.nearby.fastpair.HalfSheetResources;
import com.android.server.nearby.fastpair.cache.DiscoveryItem;
+import com.google.common.base.Objects;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+import java.util.concurrent.TimeUnit;
+
/**
* Responsible for show notification logic.
*/
public class FastPairNotificationManager {
- /**
- * FastPair notification manager that handle notification ui for fast pair.
- */
- public FastPairNotificationManager(Context context, DiscoveryItem item, boolean useLargeIcon,
- int notificationId) {
- }
- /**
- * FastPair notification manager that handle notification ui for fast pair.
- */
- public FastPairNotificationManager(Context context, DiscoveryItem item, boolean useLargeIcon) {
+ private static int sInstanceId = 0;
+ // Notification channel group ID for Devices notification channels.
+ private static final String DEVICES_CHANNEL_GROUP_ID = "DEVICES_CHANNEL_GROUP_ID";
+ // These channels are rebranded string because they are migrated from different channel ID they
+ // should not be changed.
+ // Channel ID for channel "Devices within reach".
+ static final String DEVICES_WITHIN_REACH_CHANNEL_ID = "DEVICES_WITHIN_REACH_REBRANDED";
+ // Channel ID for channel "Devices".
+ static final String DEVICES_CHANNEL_ID = "DEVICES_REBRANDED";
+ // Channel ID for channel "Devices with your account".
+ public static final String DEVICES_WITH_YOUR_ACCOUNT_CHANNEL_ID = "DEVICES_WITH_YOUR_ACCOUNT";
+ // Default channel importance for channel "Devices within reach".
+ private static final int DEFAULT_DEVICES_WITHIN_REACH_CHANNEL_IMPORTANCE =
+ NotificationManager.IMPORTANCE_HIGH;
+ // Default channel importance for channel "Devices".
+ private static final int DEFAULT_DEVICES_CHANNEL_IMPORTANCE =
+ NotificationManager.IMPORTANCE_LOW;
+ // Default channel importance for channel "Devices with your account".
+ private static final int DEFAULT_DEVICES_WITH_YOUR_ACCOUNT_CHANNEL_IMPORTANCE =
+ NotificationManager.IMPORTANCE_MIN;
+
+ /** Fixed notification ID that won't duplicated with {@code notificationId}. */
+ private static final int MAGIC_PAIR_NOTIFICATION_ID = "magic_pair_notification_id".hashCode();
+ /** Fixed notification ID that won't duplicated with {@code mNotificationId}. */
+ @VisibleForTesting
+ static final int PAIR_SUCCESS_NOTIFICATION_ID = MAGIC_PAIR_NOTIFICATION_ID - 1;
+ /** Fixed notification ID for showing the pairing failure notification. */
+ @VisibleForTesting static final int PAIR_FAILURE_NOTIFICATION_ID =
+ MAGIC_PAIR_NOTIFICATION_ID - 3;
+
+ /**
+ * The amount of delay enforced between notifications. The system only allows 10 notifications /
+ * second, but delays in the binder IPC can cause overlap.
+ */
+ private static final long MIN_NOTIFICATION_DELAY_MILLIS = 300;
+
+ // To avoid a (really unlikely) race where the user pairs and succeeds quickly more than once,
+ // use a unique ID per session, so we can delay cancellation without worrying.
+ // This is for connecting related notifications only. Discovery notification will use item id
+ // as notification id.
+ @VisibleForTesting
+ final int mNotificationId;
+ private HalfSheetResources mResources;
+ private final FastPairNotifications mNotifications;
+ private boolean mDiscoveryNotificationEnable = true;
+ // A static cache that remembers all recently shown notifications. We use this to throttle
+ // ourselves from showing notifications too rapidly. If we attempt to show a notification faster
+ // than once every 100ms, the later notifications will be dropped and we'll show stale state.
+ // Maps from Key -> Uptime Millis
+ private final Cache<Key, Long> mNotificationCache =
+ CacheBuilder.newBuilder()
+ .maximumSize(100)
+ .expireAfterWrite(MIN_NOTIFICATION_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .build();
+ private NotificationManager mNotificationManager;
+
+ /**
+ * FastPair notification manager that handle notification ui for fast pair.
+ */
+ @VisibleForTesting
+ public FastPairNotificationManager(Context context, int notificationId,
+ NotificationManager notificationManager, HalfSheetResources resources) {
+ mNotificationId = notificationId;
+ mNotificationManager = notificationManager;
+ mResources = resources;
+ mNotifications = new FastPairNotifications(context, mResources);
+
+ configureDevicesNotificationChannels();
+ }
+
+ /**
+ * FastPair notification manager that handle notification ui for fast pair.
+ */
+ public FastPairNotificationManager(Context context, int notificationId) {
+ this(context, notificationId, context.getSystemService(NotificationManager.class),
+ new HalfSheetResources(context));
+ }
+
+ /**
+ * FastPair notification manager that handle notification ui for fast pair.
+ */
+ public FastPairNotificationManager(Context context) {
+ this(context, /* notificationId= */ MAGIC_PAIR_NOTIFICATION_ID + sInstanceId);
+
+ sInstanceId++;
+ }
+
+ /**
+ * Shows the notification when found saved device. A notification will be like
+ * "Your saved device is available."
+ * This uses item id as notification Id. This should be disabled when connecting starts.
+ */
+ public void showDiscoveryNotification(DiscoveryItem item, byte[] accountKey) {
+ if (mDiscoveryNotificationEnable) {
+ Log.v(TAG, "the discovery notification is disabled");
+ return;
+ }
+
+ show(item.getId().hashCode(), mNotifications.discoveryNotification(item, accountKey));
}
/**
* Shows pairing in progress notification.
*/
- public void showConnectingNotification() {}
+ public void showConnectingNotification(DiscoveryItem item) {
+ disableShowDiscoveryNotification();
+ cancel(PAIR_FAILURE_NOTIFICATION_ID);
+ show(mNotificationId, mNotifications.progressNotification(item));
+ }
/**
- * Shows success notification
+ * Shows when Fast Pair successfully pairs the headset.
*/
public void showPairingSucceededNotification(
- @Nullable String companionApp,
+ DiscoveryItem item,
int batteryLevel,
- @Nullable String deviceName,
- String address) {
-
+ @Nullable String deviceName) {
+ enableShowDiscoveryNotification();
+ cancel(mNotificationId);
+ show(PAIR_SUCCESS_NOTIFICATION_ID,
+ mNotifications
+ .pairingSucceededNotification(
+ batteryLevel, deviceName, item.getTitle(), item));
}
/**
* Shows failed notification.
*/
- public void showPairingFailedNotification(byte[] accountKey) {
-
+ public synchronized void showPairingFailedNotification(DiscoveryItem item, byte[] accountKey) {
+ enableShowDiscoveryNotification();
+ cancel(mNotificationId);
+ show(PAIR_FAILURE_NOTIFICATION_ID,
+ mNotifications.showPairingFailedNotification(item, accountKey));
}
/**
@@ -68,4 +183,98 @@
*/
public void notifyPairingProcessDone(boolean success, boolean forceNotify,
String privateAddress, String publicAddress) {}
+
+ /** Enables the discovery notification when pairing is in progress */
+ public void enableShowDiscoveryNotification() {
+ Log.v(TAG, "enabling discovery notification");
+ mDiscoveryNotificationEnable = true;
+ }
+
+ /** Disables the discovery notification when pairing is in progress */
+ public synchronized void disableShowDiscoveryNotification() {
+ Log.v(TAG, "disabling discovery notification");
+ mDiscoveryNotificationEnable = false;
+ }
+
+ private void show(int id, Notification notification) {
+ mNotificationManager.notify(id, notification);
+ }
+
+ /**
+ * Configures devices related notification channels, including "Devices" and "Devices within
+ * reach" channels.
+ */
+ private void configureDevicesNotificationChannels() {
+ mNotificationManager.createNotificationChannelGroup(
+ new NotificationChannelGroup(
+ DEVICES_CHANNEL_GROUP_ID,
+ mResources.get().getString(R.string.common_devices)));
+ mNotificationManager.createNotificationChannel(
+ createNotificationChannel(
+ DEVICES_WITHIN_REACH_CHANNEL_ID,
+ mResources.get().getString(R.string.devices_within_reach_channel_name),
+ DEFAULT_DEVICES_WITHIN_REACH_CHANNEL_IMPORTANCE,
+ DEVICES_CHANNEL_GROUP_ID));
+ mNotificationManager.createNotificationChannel(
+ createNotificationChannel(
+ DEVICES_CHANNEL_ID,
+ mResources.get().getString(R.string.common_devices),
+ DEFAULT_DEVICES_CHANNEL_IMPORTANCE,
+ DEVICES_CHANNEL_GROUP_ID));
+ mNotificationManager.createNotificationChannel(
+ createNotificationChannel(
+ DEVICES_WITH_YOUR_ACCOUNT_CHANNEL_ID,
+ mResources.get().getString(R.string.devices_with_your_account_channel_name),
+ DEFAULT_DEVICES_WITH_YOUR_ACCOUNT_CHANNEL_IMPORTANCE,
+ DEVICES_CHANNEL_GROUP_ID));
+ }
+
+ private NotificationChannel createNotificationChannel(
+ String channelId, String channelName, int channelImportance, String channelGroupId) {
+ NotificationChannel channel =
+ new NotificationChannel(channelId, channelName, channelImportance);
+ channel.setGroup(channelGroupId);
+ if (channelImportance >= NotificationManager.IMPORTANCE_HIGH) {
+ channel.setSound(/* sound= */ null, /* audioAttributes= */ null);
+ // Disable vibration. Otherwise, the silent sound triggers a vibration if your
+ // ring volume is set to vibrate (aka turned down all the way).
+ channel.enableVibration(false);
+ }
+
+ return channel;
+ }
+
+ /** Cancel a previously shown notification. */
+ public void cancel(int id) {
+ try {
+ mNotificationManager.cancel(id);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Failed to cancel notification " + id, e);
+ }
+ mNotificationCache.invalidate(new Key(id));
+ }
+
+ private static final class Key {
+ @Nullable final String mTag;
+ final int mId;
+
+ Key(int id) {
+ this.mTag = null;
+ this.mId = id;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (o instanceof Key) {
+ Key that = (Key) o;
+ return Objects.equal(mTag, that.mTag) && (mId == that.mId);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(mTag == null ? 0 : mTag, mId);
+ }
+ }
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotifications.java b/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotifications.java
new file mode 100644
index 0000000..3b4eef8
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/notification/FastPairNotifications.java
@@ -0,0 +1,207 @@
+/*
+ * 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 com.android.server.nearby.fastpair.notification;
+
+import static com.android.nearby.halfsheet.constants.Constant.ACTION_FAST_PAIR;
+import static com.android.server.nearby.fastpair.UserActionHandler.EXTRA_FAST_PAIR_SECRET;
+import static com.android.server.nearby.fastpair.UserActionHandler.EXTRA_ITEM_ID;
+import static com.android.server.nearby.fastpair.notification.FastPairNotificationManager.DEVICES_WITHIN_REACH_CHANNEL_ID;
+
+import static com.google.common.io.BaseEncoding.base16;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
+import android.provider.Settings;
+
+import com.android.nearby.halfsheet.R;
+import com.android.server.nearby.common.fastpair.IconUtils;
+import com.android.server.nearby.fastpair.HalfSheetResources;
+import com.android.server.nearby.fastpair.cache.DiscoveryItem;
+
+import service.proto.Cache;
+
+/**
+ * Collection of utilities to create {@link Notification} objects that are displayed through {@link
+ * FastPairNotificationManager}.
+ */
+public class FastPairNotifications {
+
+ private final Context mContext;
+ private final HalfSheetResources mResources;
+ /**
+ * Note: Idea copied from Google.
+ *
+ * <p>Request code used for notification pending intents (executed on tap, dismiss).
+ *
+ * <p>Android only keeps one PendingIntent instance if it thinks multiple pending intents match.
+ * As comparing PendingIntents/Intents does not inspect the data in the extras, multiple pending
+ * intents can conflict. This can have surprising consequences (see b/68702692#comment8).
+ *
+ * <p>We also need to avoid conflicts with notifications started by an earlier launch of the app
+ * so use the truncated uptime of when the class was instantiated. The uptime will only overflow
+ * every ~50 days, and even then chances of conflict will be rare.
+ */
+ private static int sRequestCode = (int) SystemClock.elapsedRealtime();
+
+ public FastPairNotifications(Context context, HalfSheetResources resources) {
+ this.mContext = context;
+ this.mResources = resources;
+ }
+
+ /**
+ * Creates the initial "Your saved device is available" notification when subsequent pairing
+ * is available.
+ * @param item discovered item which contains title and item id
+ * @param accountKey used for generating intent for pairing
+ */
+ public Notification discoveryNotification(DiscoveryItem item, byte[] accountKey) {
+ Notification.Builder builder =
+ newBaseBuilder(item)
+ .setContentTitle(mResources.getString(R.string.fast_pair_your_device))
+ .setContentText(item.getTitle())
+ .setContentIntent(getPairIntent(item.getCopyOfStoredItem(), accountKey))
+ .setCategory(Notification.CATEGORY_RECOMMENDATION)
+ .setAutoCancel(false);
+ return builder.build();
+ }
+
+ /**
+ * Creates the in progress "Connecting" notification when the device and headset are paring.
+ */
+ public Notification progressNotification(DiscoveryItem item) {
+ String summary = mResources.getString(R.string.common_connecting);
+ Notification.Builder builder =
+ newBaseBuilder(item)
+ .setTickerForAccessibility(summary)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setContentTitle(mResources.getString(R.string.fast_pair_your_device))
+ .setContentText(summary)
+ // Intermediate progress bar.
+ .setProgress(0, 0, true)
+ // Tapping does not dismiss this.
+ .setAutoCancel(false);
+
+ return builder.build();
+ }
+
+ /**
+ * Creates paring failed notification.
+ */
+ public Notification showPairingFailedNotification(DiscoveryItem item, byte[] accountKey) {
+ String couldNotPair = mResources.getString(R.string.fast_pair_unable_to_connect);
+ String notificationContent;
+ if (accountKey != null) {
+ notificationContent = mResources.getString(
+ R.string.fast_pair_turn_on_bt_device_pairing_mode);
+ } else {
+ notificationContent =
+ mResources.getString(R.string.fast_pair_unable_to_connect_description);
+ }
+ Notification.Builder builder =
+ newBaseBuilder(item)
+ .setTickerForAccessibility(couldNotPair)
+ .setCategory(Notification.CATEGORY_ERROR)
+ .setContentTitle(couldNotPair)
+ .setContentText(notificationContent)
+ .setContentIntent(getBluetoothSettingsIntent())
+ // Dismissing completes the attempt.
+ .setDeleteIntent(getBluetoothSettingsIntent());
+ return builder.build();
+
+ }
+
+ /**
+ * Creates paring successfully notification.
+ */
+ public Notification pairingSucceededNotification(
+ int batteryLevel,
+ @Nullable String deviceName,
+ String modelName,
+ DiscoveryItem item) {
+ final String contentText;
+ StringBuilder contentTextBuilder = new StringBuilder();
+ contentTextBuilder.append(modelName);
+ if (batteryLevel >= 0 && batteryLevel <= 100) {
+ contentTextBuilder
+ .append("\n")
+ .append(mResources.getString(R.string.common_battery_level, batteryLevel));
+ }
+ String pairingComplete =
+ deviceName == null
+ ? mResources.getString(R.string.fast_pair_device_ready)
+ : mResources.getString(
+ R.string.fast_pair_device_ready_with_device_name, deviceName);
+ contentText = contentTextBuilder.toString();
+ Notification.Builder builder =
+ newBaseBuilder(item)
+ .setTickerForAccessibility(pairingComplete)
+ .setCategory(Notification.CATEGORY_STATUS)
+ .setContentTitle(pairingComplete)
+ .setContentText(contentText);
+
+ return builder.build();
+ }
+
+ private PendingIntent getPairIntent(Cache.StoredDiscoveryItem item, byte[] accountKey) {
+ Intent intent =
+ new Intent(ACTION_FAST_PAIR)
+ .putExtra(EXTRA_ITEM_ID, item.getId())
+ // Encode account key as a string instead of bytes so that it can be passed
+ // to the string representation of the intent.
+ .putExtra(EXTRA_FAST_PAIR_SECRET, base16().encode(accountKey))
+ .setPackage(mContext.getPackageName());
+ return PendingIntent.getBroadcast(mContext, sRequestCode++, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ }
+
+ private PendingIntent getBluetoothSettingsIntent() {
+ Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
+ return PendingIntent.getActivity(mContext, sRequestCode++, intent,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+ }
+
+ private LargeHeadsUpNotificationBuilder newBaseBuilder(DiscoveryItem item) {
+ LargeHeadsUpNotificationBuilder builder =
+ (LargeHeadsUpNotificationBuilder)
+ (new LargeHeadsUpNotificationBuilder(
+ mContext,
+ DEVICES_WITHIN_REACH_CHANNEL_ID,
+ /* largeIcon= */ true)
+ .setIsDevice(true)
+ // Tapping does not dismiss this.
+ .setSmallIcon(Icon.createWithResource(
+ mResources.getResourcesContext(),
+ R.drawable.quantum_ic_devices_other_vd_theme_24)))
+ .setLargeIcon(IconUtils.addWhiteCircleBackground(
+ mResources.getResourcesContext(), item.getIcon()))
+ // Dismissible.
+ .setOngoing(false)
+ // Timestamp is not relevant, hide it.
+ .setShowWhen(false)
+ .setColor(mResources.getColor(R.color.discovery_activity_accent))
+ .setLocalOnly(true)
+ // don't show these notifications on wear devices
+ .setAutoCancel(true);
+
+ return builder;
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/notification/LargeHeadsUpNotificationBuilder.java b/nearby/service/java/com/android/server/nearby/fastpair/notification/LargeHeadsUpNotificationBuilder.java
new file mode 100644
index 0000000..ec41d76
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/notification/LargeHeadsUpNotificationBuilder.java
@@ -0,0 +1,188 @@
+/*
+ * 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 com.android.server.nearby.fastpair.notification;
+
+import static com.android.server.nearby.fastpair.Constant.TAG;
+
+import android.annotation.LayoutRes;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.RemoteViews;
+
+import com.android.nearby.halfsheet.R;
+
+/** Wrapper class for creating larger heads up notifications. */
+public class LargeHeadsUpNotificationBuilder extends FastPairNotificationBuilder {
+ private final boolean mLargeIcon;
+ private final RemoteViews mNotification;
+ private final RemoteViews mNotificationCollapsed;
+
+ @Nullable private Runnable mLargeIconAction;
+ @Nullable private Runnable mProgressAction;
+
+ public LargeHeadsUpNotificationBuilder(Context context, String channelId, boolean largeIcon) {
+ super(context, channelId);
+
+ this.mLargeIcon = largeIcon;
+ this.mNotification = getRemoteViews(R.layout.fast_pair_heads_up_notification);
+ this.mNotificationCollapsed = getRemoteViews(R.layout.fast_pair_heads_up_notification);
+
+ if (mNotification != null) {
+ mNotificationCollapsed.setViewVisibility(android.R.id.secondaryProgress, View.GONE);
+ }
+ }
+
+ /**
+ * Create a new RemoteViews object that will display the views contained
+ * fast_pair_heads_up_notification layout.
+ */
+ @Nullable
+ public RemoteViews getRemoteViews(@LayoutRes int layoutId) {
+ return new RemoteViews(mPackageName, layoutId);
+ }
+
+ @Override
+ public Notification.Builder setContentTitle(@Nullable CharSequence title) {
+ if (mNotification != null) {
+ mNotification.setTextViewText(android.R.id.title, title);
+ }
+ if (mNotificationCollapsed != null) {
+ mNotificationCollapsed.setTextViewText(android.R.id.title, title);
+ // Collapsed mode does not need additional lines.
+ mNotificationCollapsed.setInt(android.R.id.title, "setMaxLines", 1);
+ }
+ return super.setContentTitle(title);
+ }
+
+ @Override
+ public Notification.Builder setContentText(@Nullable CharSequence text) {
+ if (mNotification != null) {
+ mNotification.setTextViewText(android.R.id.text1, text);
+ }
+ if (mNotificationCollapsed != null) {
+ mNotificationCollapsed.setTextViewText(android.R.id.text1, text);
+ // Collapsed mode does not need additional lines.
+ mNotificationCollapsed.setInt(android.R.id.text1, "setMaxLines", 1);
+ }
+
+ return super.setContentText(text);
+ }
+
+ @Override
+ public Notification.Builder setSubText(@Nullable CharSequence subText) {
+ if (mNotification != null) {
+ mNotification.setTextViewText(android.R.id.text2, subText);
+ }
+ if (mNotificationCollapsed != null) {
+ mNotificationCollapsed.setTextViewText(android.R.id.text2, subText);
+ }
+ return super.setSubText(subText);
+ }
+
+ @Override
+ public Notification.Builder setLargeIcon(@Nullable Bitmap bitmap) {
+ RemoteViews image =
+ getRemoteViews(
+ useLargeIcon()
+ ? R.layout.fast_pair_heads_up_notification_large_image
+ : R.layout.fast_pair_heads_up_notification_small_image);
+ if (image == null) {
+ return super.setLargeIcon(bitmap);
+ }
+ image.setImageViewBitmap(android.R.id.icon, bitmap);
+
+ if (mNotification != null) {
+ mNotification.removeAllViews(android.R.id.icon1);
+ mNotification.addView(android.R.id.icon1, image);
+ }
+ if (mNotificationCollapsed != null) {
+ mNotificationCollapsed.removeAllViews(android.R.id.icon1);
+ mNotificationCollapsed.addView(android.R.id.icon1, image);
+ // In Android S, if super.setLargeIcon() is called, there will be an extra icon on
+ // top-right.
+ // But we still need to store this setting for the default UI when something wrong.
+ mLargeIconAction = () -> super.setLargeIcon(bitmap);
+ return this;
+ }
+ return super.setLargeIcon(bitmap);
+ }
+
+ @Override
+ public Notification.Builder setProgress(int max, int progress, boolean indeterminate) {
+ if (mNotification != null) {
+ mNotification.setViewVisibility(android.R.id.secondaryProgress, View.VISIBLE);
+ mNotification.setProgressBar(android.R.id.progress, max, progress, indeterminate);
+ }
+ if (mNotificationCollapsed != null) {
+ mNotificationCollapsed.setViewVisibility(android.R.id.secondaryProgress, View.VISIBLE);
+ mNotificationCollapsed.setProgressBar(android.R.id.progress, max, progress,
+ indeterminate);
+ // In Android S, if super.setProgress() is called, there will be an extra progress bar.
+ // But we still need to store this setting for the default UI when something wrong.
+ mProgressAction = () -> super.setProgress(max, progress, indeterminate);
+ return this;
+ }
+ return super.setProgress(max, progress, indeterminate);
+ }
+
+ @Override
+ public Notification build() {
+ if (mNotification != null) {
+ boolean buildSuccess = false;
+ try {
+ // Attempt to apply the remote views. This verifies that all of the resources are
+ // correctly available.
+ // If it fails, fall back to a non-custom notification.
+ mNotification.apply(mContext, new LinearLayout(mContext));
+ if (mNotificationCollapsed != null) {
+ mNotificationCollapsed.apply(mContext, new LinearLayout(mContext));
+ }
+ buildSuccess = true;
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "Failed to build notification, not setting custom view.", e);
+ }
+
+ if (buildSuccess) {
+ if (mNotificationCollapsed != null) {
+ setStyle(new Notification.DecoratedCustomViewStyle());
+ setCustomContentView(mNotificationCollapsed);
+ setCustomBigContentView(mNotification);
+ } else {
+ setCustomHeadsUpContentView(mNotification);
+ }
+ } else {
+ if (mLargeIconAction != null) {
+ mLargeIconAction.run();
+ }
+ if (mProgressAction != null) {
+ mProgressAction.run();
+ }
+ }
+ }
+ return super.build();
+ }
+
+ private boolean useLargeIcon() {
+ return mLargeIcon;
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandler.java b/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandler.java
index c95f74f..e56f1ea 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandler.java
@@ -63,9 +63,10 @@
public void onPairingStarted() {
super.onPairingStarted();
// Half sheet is not in the foreground reshow half sheet, also avoid showing HalfSheet on TV
- if (!mFastPairHalfSheetManager.getHalfSheetForegroundState()) {
+ if (!mFastPairHalfSheetManager.getHalfSheetForeground()) {
mFastPairHalfSheetManager.showPairingHalfSheet(mItemResurface);
}
+ mFastPairHalfSheetManager.reportActivelyPairing();
mFastPairHalfSheetManager.disableDismissRunnable();
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandler.java b/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandler.java
index d469c45..5317673 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandler.java
@@ -20,7 +20,6 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
-import android.text.TextUtils;
import android.util.Log;
import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection;
@@ -68,7 +67,7 @@
@Override
public void onReadyToPair() {
super.onReadyToPair();
- mFastPairNotificationManager.showConnectingNotification();
+ mFastPairNotificationManager.showConnectingNotification(mItem);
}
@Override
@@ -79,32 +78,24 @@
String address) {
String deviceName = super.onPairedCallbackCalled(connection, accountKey, footprints,
address);
-
int batteryLevel = -1;
BluetoothManager bluetoothManager = mContext.getSystemService(BluetoothManager.class);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
- if (bluetoothAdapter != null) {
- // Need to check battery level here set that to -1 for now
- batteryLevel = -1;
+ if (address != null && bluetoothAdapter != null) {
+ batteryLevel = bluetoothAdapter.getRemoteDevice(address).getBatteryLevel();
} else {
- Log.v(
- "NotificationPairingProgressHandler",
- "onPairedCallbackCalled getBatteryLevel failed,"
- + " adapter is null");
+ Log.v(TAG, "onPairedCallbackCalled getBatteryLevel failed");
}
- mFastPairNotificationManager.showPairingSucceededNotification(
- !TextUtils.isEmpty(mCompanionApp) ? mCompanionApp : null,
- batteryLevel,
- deviceName,
- address);
+ mFastPairNotificationManager
+ .showPairingSucceededNotification(mItem, batteryLevel, deviceName);
return deviceName;
}
@Override
public void onPairingFailed(Throwable throwable) {
super.onPairingFailed(throwable);
- mFastPairNotificationManager.showPairingFailedNotification(mAccountKey);
+ mFastPairNotificationManager.showPairingFailedNotification(mItem, mAccountKey);
mFastPairNotificationManager.notifyPairingProcessDone(
/* success= */ false,
/* forceNotify= */ false,
@@ -115,6 +106,19 @@
@Override
public void onPairingSuccess(String address) {
super.onPairingSuccess(address);
+ int batteryLevel = -1;
+
+ BluetoothManager bluetoothManager = mContext.getSystemService(BluetoothManager.class);
+ BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+ String deviceName = null;
+ if (address != null && bluetoothAdapter != null) {
+ deviceName = bluetoothAdapter.getRemoteDevice(address).getName();
+ batteryLevel = bluetoothAdapter.getRemoteDevice(address).getBatteryLevel();
+ } else {
+ Log.v(TAG, "onPairedCallbackCalled getBatteryLevel failed");
+ }
+ mFastPairNotificationManager
+ .showPairingSucceededNotification(mItem, batteryLevel, deviceName);
mFastPairNotificationManager.notifyPairingProcessDone(
/* success= */ true,
/* forceNotify= */ false,
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBase.java b/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBase.java
index 5fb05d5..6f2dc40 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBase.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBase.java
@@ -35,6 +35,7 @@
/** Base class for pairing progress handler. */
public abstract class PairingProgressHandlerBase {
+ protected static final String TAG = "FPPairingHandler";
protected final Context mContext;
protected final DiscoveryItem mItem;
@Nullable
@@ -49,7 +50,6 @@
this.mItem = item;
}
-
/**
* Pairing progress init function.
*/
@@ -75,59 +75,55 @@
new HalfSheetPairingProgressHandler(context, item, companionApp, accountKey);
}
-
- Log.v("PairingHandler",
- "PairingProgressHandler:Create "
- + item.getMacAddress() + " for pairing");
+ Log.v(TAG, "PairingProgressHandler:Create " + item.getMacAddress() + " for pairing");
return pairingProgressHandlerBase;
}
-
/**
* Function calls when pairing start.
*/
public void onPairingStarted() {
- Log.v("PairingHandler", "PairingProgressHandler:onPairingStarted");
+ Log.v(TAG, "PairingProgressHandler:onPairingStarted");
}
/**
* Waits for screen to unlock.
*/
public void onWaitForScreenUnlock() {
- Log.v("PairingHandler", "PairingProgressHandler:onWaitForScreenUnlock");
+ Log.v(TAG, "PairingProgressHandler:onWaitForScreenUnlock");
}
/**
* Function calls when screen unlock.
*/
public void onScreenUnlocked() {
- Log.v("PairingHandler", "PairingProgressHandler:onScreenUnlocked");
+ Log.v(TAG, "PairingProgressHandler:onScreenUnlocked");
}
/**
* Calls when the handler is ready to pair.
*/
public void onReadyToPair() {
- Log.v("PairingHandler", "PairingProgressHandler:onReadyToPair");
+ Log.v(TAG, "PairingProgressHandler:onReadyToPair");
}
/**
* Helps to set up pairing preference.
*/
public void onSetupPreferencesBuilder(Preferences.Builder builder) {
- Log.v("PairingHandler", "PairingProgressHandler:onSetupPreferencesBuilder");
+ Log.v(TAG, "PairingProgressHandler:onSetupPreferencesBuilder");
}
/**
* Calls when pairing setup complete.
*/
public void onPairingSetupCompleted() {
- Log.v("PairingHandler", "PairingProgressHandler:onPairingSetupCompleted");
+ Log.v(TAG, "PairingProgressHandler:onPairingSetupCompleted");
}
/** Called while pairing if needs to handle the passkey confirmation by Ui. */
public void onHandlePasskeyConfirmation(BluetoothDevice device, int passkey) {
- Log.v("PairingHandler", "PairingProgressHandler:onHandlePasskeyConfirmation");
+ Log.v(TAG, "PairingProgressHandler:onHandlePasskeyConfirmation");
}
/**
@@ -149,7 +145,7 @@
byte[] accountKey,
FootprintsDeviceManager footprints,
String address) {
- Log.v("PairingHandler",
+ Log.v(TAG,
"PairingProgressHandler:onPairedCallbackCalled with address: "
+ address);
@@ -166,7 +162,7 @@
public byte[] getKeyForLocalCache(
byte[] accountKey, FastPairConnection connection,
FastPairConnection.SharedSecret sharedSecret) {
- Log.v("PairingHandler", "PairingProgressHandler:getKeyForLocalCache");
+ Log.v(TAG, "PairingProgressHandler:getKeyForLocalCache");
return accountKey != null ? accountKey : connection.getExistingAccountKey();
}
@@ -174,14 +170,14 @@
* Function handles pairing fail.
*/
public void onPairingFailed(Throwable throwable) {
- Log.w("PairingHandler", "PairingProgressHandler:onPairingFailed");
+ Log.w(TAG, "PairingProgressHandler:onPairingFailed");
}
/**
* Function handles pairing success.
*/
public void onPairingSuccess(String address) {
- Log.v("PairingHandler", "PairingProgressHandler:onPairingSuccess with address: "
+ Log.v(TAG, "PairingProgressHandler:onPairingSuccess with address: "
+ maskBluetoothAddress(address));
}
@@ -193,7 +189,7 @@
@Nullable byte[] existingAccountKey) {
if (isThroughFastPair2InitialPairing(item, accountKey) && existingAccountKey == null) {
// enable the save to footprint
- Log.v("PairingHandler", "footprint should call opt in here");
+ Log.v(TAG, "footprint should call opt in here");
}
}
diff --git a/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java b/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java
index 8b2db50..deb5167 100644
--- a/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java
+++ b/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java
@@ -38,6 +38,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.Constant;
import java.util.Arrays;
import java.util.List;
@@ -72,6 +73,11 @@
@Override
public void onLost(@NonNull NearbyDevice device) {}
+
+ @Override
+ public void onError(int errorCode) {
+ Log.w(Constant.TAG, "[PresenceManager] Scan error is " + errorCode);
+ }
};
private final BroadcastReceiver mScreenBroadcastReceiver =
diff --git a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
index 41d5686..c3f389b 100644
--- a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
@@ -28,6 +28,7 @@
import android.nearby.NearbyDeviceParcelable;
import android.nearby.NearbyManager;
import android.nearby.PresenceScanFilter;
+import android.nearby.ScanCallback;
import android.nearby.ScanFilter;
import android.nearby.ScanRequest;
import android.os.IBinder;
@@ -82,7 +83,7 @@
Log.w(TAG, "[DiscoveryProviderManager] scan permission revoked "
+ "- not forwarding results");
try {
- record.getScanListener().onError();
+ record.getScanListener().onError(ScanCallback.ERROR_PERMISSION_DENIED);
} catch (RemoteException e) {
Log.w(TAG, "DiscoveryProviderManager failed to report error.", e);
}
diff --git a/nearby/service/java/com/android/server/nearby/util/ArrayUtils.java b/nearby/service/java/com/android/server/nearby/util/ArrayUtils.java
index 599843c..35251d8 100644
--- a/nearby/service/java/com/android/server/nearby/util/ArrayUtils.java
+++ b/nearby/service/java/com/android/server/nearby/util/ArrayUtils.java
@@ -45,4 +45,11 @@
}
return result;
}
+
+ /**
+ * @return true when the array is null or length is 0
+ */
+ public static boolean isEmpty(byte[] bytes) {
+ return bytes == null || bytes.length == 0;
+ }
}
diff --git a/nearby/service/java/com/android/server/nearby/util/Clock.java b/nearby/service/java/com/android/server/nearby/util/Clock.java
new file mode 100644
index 0000000..037b6f9
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/util/Clock.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.server.nearby.util;
+
+import android.os.SystemClock;
+
+/** Wrapper interface for time operations. Allows replacement of clock operations for testing. */
+public interface Clock {
+
+ /**
+ * Get the current time of the clock in milliseconds.
+ *
+ * @return Current time in milliseconds.
+ */
+ long currentTimeMillis();
+
+ /**
+ * Returns milliseconds since boot, including time spent in sleep.
+ *
+ * @return Current time since boot in milliseconds.
+ */
+ long elapsedRealtime();
+
+ /**
+ * Returns the current timestamp of the most precise timer available on the local system, in
+ * nanoseconds.
+ *
+ * @return Current time in nanoseconds.
+ */
+ long nanoTime();
+
+ /**
+ * Returns the time spent in the current thread, in milliseconds
+ *
+ * @return Thread time in milliseconds.
+ */
+ @SuppressWarnings("StaticOrDefaultInterfaceMethod")
+ default long currentThreadTimeMillis() {
+ return SystemClock.currentThreadTimeMillis();
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/util/DataUtils.java b/nearby/service/java/com/android/server/nearby/util/DataUtils.java
index c3bae08..12bf384 100644
--- a/nearby/service/java/com/android/server/nearby/util/DataUtils.java
+++ b/nearby/service/java/com/android/server/nearby/util/DataUtils.java
@@ -38,11 +38,12 @@
*/
public static ScanFastPairStoreItem toScanFastPairStoreItem(
GetObservedDeviceResponse observedDeviceResponse,
- @NonNull String bleAddress, @Nullable String account) {
+ @NonNull String bleAddress, @NonNull String modelId, @Nullable String account) {
Device device = observedDeviceResponse.getDevice();
String deviceName = device.getName();
return ScanFastPairStoreItem.newBuilder()
.setAddress(bleAddress)
+ .setModelId(modelId)
.setActionUrl(device.getIntentUri())
.setDeviceName(deviceName)
.setIconPng(observedDeviceResponse.getImage())
diff --git a/nearby/service/java/com/android/server/nearby/util/DefaultClock.java b/nearby/service/java/com/android/server/nearby/util/DefaultClock.java
new file mode 100644
index 0000000..61998e9
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/util/DefaultClock.java
@@ -0,0 +1,52 @@
+/*
+ * 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 com.android.server.nearby.util;
+
+import android.os.SystemClock;
+
+/** Default implementation of Clock. Instances of this class handle time operations. */
+public class DefaultClock implements Clock {
+
+ private static final DefaultClock sInstance = new DefaultClock();
+
+ /** Returns an instance of DefaultClock. */
+ public static Clock getsInstance() {
+ return sInstance;
+ }
+
+ @Override
+ public long currentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
+ @Override
+ public long elapsedRealtime() {
+ return SystemClock.elapsedRealtime();
+ }
+
+ @Override
+ public long nanoTime() {
+ return System.nanoTime();
+ }
+
+ @Override
+ public long currentThreadTimeMillis() {
+ return SystemClock.currentThreadTimeMillis();
+ }
+
+ public DefaultClock() {}
+}
diff --git a/nearby/tests/cts/fastpair/Android.bp b/nearby/tests/cts/fastpair/Android.bp
index 0410cd5..a61d180 100644
--- a/nearby/tests/cts/fastpair/Android.bp
+++ b/nearby/tests/cts/fastpair/Android.bp
@@ -41,7 +41,6 @@
"mts-tethering",
],
certificate: "platform",
- platform_apis: true,
sdk_version: "module_current",
min_sdk_version: "30",
target_sdk_version: "32",
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
deleted file mode 100644
index 2907e56..0000000
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
+++ /dev/null
@@ -1,178 +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.cts;
-
-import static android.nearby.ScanRequest.SCAN_TYPE_NEARBY_PRESENCE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.nearby.NearbyDevice;
-import android.nearby.NearbyDeviceParcelable;
-import android.nearby.PublicCredential;
-import android.os.Build;
-import android.os.Parcel;
-
-import androidx.annotation.RequiresApi;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SdkSuppress;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-public class NearbyDeviceParcelableTest {
-
- private static final String BLUETOOTH_ADDRESS = "00:11:22:33:FF:EE";
- private static final byte[] SCAN_DATA = new byte[] {1, 2, 3, 4};
- private static final byte[] SALT = new byte[] {1, 2, 3, 4};
- private static final String FAST_PAIR_MODEL_ID = "1234";
- private static final int RSSI = -60;
- private static final int TX_POWER = -10;
- private static final int ACTION = 1;
-
- private NearbyDeviceParcelable.Builder mBuilder;
-
- @Before
- public void setUp() {
- mBuilder =
- new NearbyDeviceParcelable.Builder()
- .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
- .setName("testDevice")
- .setMedium(NearbyDevice.Medium.BLE)
- .setRssi(RSSI)
- .setFastPairModelId(FAST_PAIR_MODEL_ID)
- .setBluetoothAddress(BLUETOOTH_ADDRESS)
- .setData(SCAN_DATA);
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 33, codeName = "T")
- public void testNullFields() {
- PublicCredential publicCredential =
- new PublicCredential.Builder(
- new byte[] {1},
- new byte[] {2},
- new byte[] {3},
- new byte[] {4},
- new byte[] {5})
- .build();
- NearbyDeviceParcelable nearbyDeviceParcelable =
- new NearbyDeviceParcelable.Builder()
- .setMedium(NearbyDevice.Medium.BLE)
- .setPublicCredential(publicCredential)
- .setAction(ACTION)
- .setRssi(RSSI)
- .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
- .setTxPower(TX_POWER)
- .setSalt(SALT)
- .build();
-
- assertThat(nearbyDeviceParcelable.getName()).isNull();
- assertThat(nearbyDeviceParcelable.getFastPairModelId()).isNull();
- assertThat(nearbyDeviceParcelable.getBluetoothAddress()).isNull();
- assertThat(nearbyDeviceParcelable.getData()).isNull();
- assertThat(nearbyDeviceParcelable.getMedium()).isEqualTo(NearbyDevice.Medium.BLE);
- assertThat(nearbyDeviceParcelable.getRssi()).isEqualTo(RSSI);
- assertThat(nearbyDeviceParcelable.getAction()).isEqualTo(ACTION);
- assertThat(nearbyDeviceParcelable.getPublicCredential()).isEqualTo(publicCredential);
- assertThat(nearbyDeviceParcelable.getSalt()).isEqualTo(SALT);
- assertThat(nearbyDeviceParcelable.getTxPower()).isEqualTo(TX_POWER);
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 33, codeName = "T")
- public void testWriteParcel() {
- NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.build();
-
- Parcel parcel = Parcel.obtain();
- nearbyDeviceParcelable.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- NearbyDeviceParcelable actualNearbyDevice =
- NearbyDeviceParcelable.CREATOR.createFromParcel(parcel);
- parcel.recycle();
-
- assertThat(actualNearbyDevice.getRssi()).isEqualTo(RSSI);
- assertThat(actualNearbyDevice.getFastPairModelId()).isEqualTo(FAST_PAIR_MODEL_ID);
- assertThat(actualNearbyDevice.getBluetoothAddress()).isEqualTo(BLUETOOTH_ADDRESS);
- assertThat(Arrays.equals(actualNearbyDevice.getData(), SCAN_DATA)).isTrue();
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 33, codeName = "T")
- public void testWriteParcel_nullModelId() {
- NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.setFastPairModelId(null).build();
-
- Parcel parcel = Parcel.obtain();
- nearbyDeviceParcelable.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- NearbyDeviceParcelable actualNearbyDevice =
- NearbyDeviceParcelable.CREATOR.createFromParcel(parcel);
- parcel.recycle();
-
- assertThat(actualNearbyDevice.getFastPairModelId()).isNull();
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 33, codeName = "T")
- public void testWriteParcel_nullBluetoothAddress() {
- NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.setBluetoothAddress(null).build();
- Parcel parcel = Parcel.obtain();
- nearbyDeviceParcelable.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- NearbyDeviceParcelable actualNearbyDevice =
- NearbyDeviceParcelable.CREATOR.createFromParcel(parcel);
- parcel.recycle();
-
- assertThat(actualNearbyDevice.getBluetoothAddress()).isNull();
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 33, codeName = "T")
- public void describeContents() {
- NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.setBluetoothAddress(null).build();
- assertThat(nearbyDeviceParcelable.describeContents()).isEqualTo(0);
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 33, codeName = "T")
- public void testEqual() {
- PublicCredential publicCredential =
- new PublicCredential.Builder(
- new byte[] {1},
- new byte[] {2},
- new byte[] {3},
- new byte[] {4},
- new byte[] {5})
- .build();
- NearbyDeviceParcelable nearbyDeviceParcelable1 =
- mBuilder.setPublicCredential(publicCredential).build();
- NearbyDeviceParcelable nearbyDeviceParcelable2 =
- mBuilder.setPublicCredential(publicCredential).build();
- assertThat(nearbyDeviceParcelable1.equals(nearbyDeviceParcelable2)).isTrue();
- }
-
- @Test
- public void testCreatorNewArray() {
- NearbyDeviceParcelable[] nearbyDeviceParcelables =
- NearbyDeviceParcelable.CREATOR.newArray(2);
- assertThat(nearbyDeviceParcelables.length).isEqualTo(2);
- }
-}
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 462d05a..7707ee9 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;
@@ -57,6 +58,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
/**
* TODO(b/215435939) This class doesn't include any logic yet. Because SELinux denies access to
@@ -94,7 +96,12 @@
@Override
public void onLost(@NonNull NearbyDevice device) {
}
+
+ @Override
+ public void onError(int errorCode) {
+ }
};
+
private static final Executor EXECUTOR = Executors.newSingleThreadExecutor();
@Before
@@ -159,12 +166,10 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
- public void setFastPairScanEnabled() {
- mNearbyManager.setFastPairScanEnabled(mContext, true);
- assertThat(mNearbyManager.getFastPairScanEnabled(mContext)).isTrue();
- mNearbyManager.setFastPairScanEnabled(mContext, false);
- assertThat(mNearbyManager.getFastPairScanEnabled(mContext)).isFalse();
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public void queryOffloadScanSupport() {
+ OffloadCallback callback = new OffloadCallback();
+ mNearbyManager.queryOffloadCapability(EXECUTOR, callback);
}
private void enableBluetooth() {
@@ -174,4 +179,11 @@
assertThat(BTAdapterUtils.enableAdapter(bluetoothAdapter, mContext)).isTrue();
}
}
+
+ private static class OffloadCallback implements Consumer<OffloadCapability> {
+ @Override
+ public void accept(OffloadCapability aBoolean) {
+ // no-op for now
+ }
+ }
}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/OffloadCapabilityTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/OffloadCapabilityTest.java
new file mode 100644
index 0000000..a745c7d
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/OffloadCapabilityTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.OffloadCapability;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class OffloadCapabilityTest {
+ private static final long VERSION = 123456;
+
+ @Test
+ public void testDefault() {
+ OffloadCapability offloadCapability = new OffloadCapability.Builder().build();
+
+ assertThat(offloadCapability.isFastPairSupported()).isFalse();
+ assertThat(offloadCapability.isNearbyShareSupported()).isFalse();
+ assertThat(offloadCapability.getVersion()).isEqualTo(0);
+ }
+
+ @Test
+ public void testBuilder() {
+ OffloadCapability offloadCapability = new OffloadCapability.Builder()
+ .setFastPairSupported(true)
+ .setNearbyShareSupported(true)
+ .setVersion(VERSION)
+ .build();
+
+ assertThat(offloadCapability.isFastPairSupported()).isTrue();
+ assertThat(offloadCapability.isNearbyShareSupported()).isTrue();
+ assertThat(offloadCapability.getVersion()).isEqualTo(VERSION);
+ }
+
+ @Test
+ public void testWriteParcel() {
+ OffloadCapability offloadCapability = new OffloadCapability.Builder()
+ .setFastPairSupported(true)
+ .setNearbyShareSupported(false)
+ .setVersion(VERSION)
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ offloadCapability.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ OffloadCapability capability = OffloadCapability.CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+
+ assertThat(capability.isFastPairSupported()).isTrue();
+ assertThat(capability.isNearbyShareSupported()).isFalse();
+ assertThat(capability.getVersion()).isEqualTo(VERSION);
+ }
+}
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..5ad52c2 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,39 +84,9 @@
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")
- public void testisEnableBle_defaultTrue() {
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
+ public void testIsEnableBle_defaultTrue() {
ScanRequest request = new ScanRequest.Builder()
.setScanType(SCAN_TYPE_FAST_PAIR)
.build();
@@ -128,7 +95,28 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public void testIsOffloadOnly_defaultFalse() {
+ ScanRequest request = new ScanRequest.Builder()
+ .setScanType(SCAN_TYPE_FAST_PAIR)
+ .build();
+
+ assertThat(request.isOffloadOnly()).isFalse();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public void testSetOffloadOnly_isOffloadOnlyTrue() {
+ ScanRequest request = new ScanRequest.Builder()
+ .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
+ .setOffloadOnly(true)
+ .build();
+
+ assertThat(request.isOffloadOnly()).isTrue();
+ }
+
+ @Test
+ @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 +126,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 +138,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 +150,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 +160,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 +169,7 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testCreatorNewArray() {
ScanRequest[] requests =
ScanRequest.CREATOR.newArray(2);
@@ -207,8 +195,4 @@
.addPresenceAction(action)
.build();
}
-
- private static WorkSource getWorkSource() {
- return new WorkSource(UID, APP_NAME);
- }
}
diff --git a/nearby/tests/integration/privileged/src/android/nearby/integration/privileged/NearbyManagerTest.kt b/nearby/tests/integration/privileged/src/android/nearby/integration/privileged/NearbyManagerTest.kt
index 66bab23..506b4e2 100644
--- a/nearby/tests/integration/privileged/src/android/nearby/integration/privileged/NearbyManagerTest.kt
+++ b/nearby/tests/integration/privileged/src/android/nearby/integration/privileged/NearbyManagerTest.kt
@@ -63,6 +63,8 @@
override fun onUpdated(device: NearbyDevice) {}
override fun onLost(device: NearbyDevice) {}
+
+ override fun onError(errorCode: Int) {}
}
nearbyManager.startScan(scanRequest, /* executor */ { it.run() }, scanCallback)
diff --git a/nearby/tests/integration/ui/src/android/nearby/integration/ui/NearbyHalfSheetUiMap.kt b/nearby/tests/integration/ui/src/android/nearby/integration/ui/NearbyHalfSheetUiMap.kt
index 8b19d5c..4098865 100644
--- a/nearby/tests/integration/ui/src/android/nearby/integration/ui/NearbyHalfSheetUiMap.kt
+++ b/nearby/tests/integration/ui/src/android/nearby/integration/ui/NearbyHalfSheetUiMap.kt
@@ -25,13 +25,13 @@
import androidx.test.core.app.ApplicationProvider
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
-import com.android.server.nearby.fastpair.FastPairManager
import com.android.server.nearby.util.Environment
import com.google.common.truth.Truth.assertThat
/** UiMap for Nearby Mainline Half Sheet. */
object NearbyHalfSheetUiMap {
private val PACKAGE_NAME: String = getHalfSheetApkPkgName()
+ private const val ACTION_RESOURCES_APK = "android.nearby.SHOW_HALFSHEET"
private const val ANDROID_WIDGET_BUTTON = "android.widget.Button"
private const val ANDROID_WIDGET_IMAGE_VIEW = "android.widget.ImageView"
private const val ANDROID_WIDGET_TEXT_VIEW = "android.widget.TextView"
@@ -54,8 +54,7 @@
fun getHalfSheetApkPkgName(): String {
val appContext = ApplicationProvider.getApplicationContext<Context>()
val resolveInfos: MutableList<ResolveInfo> =
- appContext.packageManager.queryIntentActivities(
- Intent(FastPairManager.ACTION_RESOURCES_APK),
+ appContext.packageManager.queryIntentActivities(Intent(ACTION_RESOURCES_APK),
ResolveInfoFlags.of(MATCH_SYSTEM_ONLY.toLong())
)
@@ -68,4 +67,4 @@
Log.i("NearbyHalfSheetUiMap", "Found half-sheet APK at: $halfSheetApkPkgName")
return halfSheetApkPkgName
}
-}
\ No newline at end of file
+}
diff --git a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/events/ScanCallbackEvents.kt b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/events/ScanCallbackEvents.kt
index 363355f..02847b5 100644
--- a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/events/ScanCallbackEvents.kt
+++ b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/events/ScanCallbackEvents.kt
@@ -40,4 +40,10 @@
putString("device", device.toString())
}
}
-}
\ No newline at end of file
+
+ override fun onError(errorCode: Int) {
+ postSnippetEvent(callbackId, "onError") {
+ putString("error", errorCode.toString())
+ }
+ }
+}
diff --git a/nearby/tests/multidevices/host/Android.bp b/nearby/tests/multidevices/host/Android.bp
index b81032d..b6c1c9d 100644
--- a/nearby/tests/multidevices/host/Android.bp
+++ b/nearby/tests/multidevices/host/Android.bp
@@ -22,7 +22,10 @@
name: "NearbyMultiDevicesTestSuite",
main: "suite_main.py",
srcs: ["*.py"],
- libs: ["NearbyMultiDevicesHostHelper"],
+ libs: [
+ "NearbyMultiDevicesHostHelper",
+ "mobly",
+ ],
test_suites: [
"general-tests",
"mts-tethering",
@@ -38,6 +41,11 @@
// Package the JSON metadata with the Mobly test.
"test_data/**/*",
],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
}
python_library_host {
diff --git a/nearby/tests/multidevices/host/AndroidTest.xml b/nearby/tests/multidevices/host/AndroidTest.xml
index c1f6a70..fff0ed1 100644
--- a/nearby/tests/multidevices/host/AndroidTest.xml
+++ b/nearby/tests/multidevices/host/AndroidTest.xml
@@ -42,11 +42,6 @@
<option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
<option name="run-command" value="wm dismiss-keyguard" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer">
- <!-- Any python dependencies can be specified and will be installed with pip -->
- <!-- TODO(b/225958696): Import python dependencies -->
- <option name="dep-module" value="mobly" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
<option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
<option name="screen-always-on" value="on" />
diff --git a/nearby/tests/unit/Android.bp b/nearby/tests/unit/Android.bp
index 9b35452..8a8aeab 100644
--- a/nearby/tests/unit/Android.bp
+++ b/nearby/tests/unit/Android.bp
@@ -29,6 +29,7 @@
"android.test.base",
"android.test.mock",
"android.test.runner",
+ "HalfSheetUX",
],
compile_multilib: "both",
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)
diff --git a/nearby/tests/unit/src/com/android/server/nearby/common/ble/BleSightingTest.java b/nearby/tests/unit/src/com/android/server/nearby/common/ble/BleSightingTest.java
index d259851..3443b53 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/common/ble/BleSightingTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/common/ble/BleSightingTest.java
@@ -93,7 +93,7 @@
assertThat(sighting.getTimestampNanos())
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(TIME_EPOCH_MILLIS));
assertThat(sighting.toString()).isEqualTo(
- "BleSighting{device=00:11:22:33:44:55,"
+ "BleSighting{device=" + mBluetoothDevice1 + ","
+ " bleRecord=BleRecord [advertiseFlags=-1,"
+ " serviceUuids=[],"
+ " manufacturerSpecificData={}, serviceData={},"
diff --git a/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/EventTest.java b/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/EventTest.java
index 1b63ad0..f10f66d 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/EventTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/EventTest.java
@@ -63,7 +63,7 @@
assertThat(event.isFailure()).isTrue();
assertThat(event.toString()).isEqualTo(
"Event{eventCode=1120, timestamp=1234, profile=1, "
- + "bluetoothDevice=11:22:33:44:55:66, "
+ + "bluetoothDevice=" + BLUETOOTH_DEVICE + ", "
+ "exception=java.lang.Exception: Test exception}");
Parcel parcel = Parcel.obtain();
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairAdvHandlerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairAdvHandlerTest.java
index 39ea5a9..900b618 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairAdvHandlerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairAdvHandlerTest.java
@@ -19,15 +19,19 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.accounts.Account;
import android.content.Context;
import android.nearby.FastPairDevice;
import com.android.server.nearby.common.bloomfilter.BloomFilter;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.cache.DiscoveryItem;
+import com.android.server.nearby.fastpair.cache.FastPairCacheManager;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
import com.android.server.nearby.fastpair.notification.FastPairNotificationManager;
import com.android.server.nearby.provider.FastPairDataProvider;
@@ -40,6 +44,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.time.Clock;
+import java.util.List;
+
import service.proto.Cache;
import service.proto.Data;
import service.proto.Rpcs;
@@ -54,20 +61,38 @@
@Mock
private FastPairNotificationManager mFastPairNotificationManager;
@Mock
+ private FastPairCacheManager mFastPairCacheManager;
+ @Mock
+ private FastPairController mFastPairController;
+ @Mock
+ private Data.FastPairDeviceWithAccountKey mFastPairDeviceWithAccountKey;
+ @Mock
private BloomFilter mBloomFilter;
@Mock
- Cache.StoredDiscoveryItem mStoredDiscoveryItem;
- @Mock
Cache.StoredFastPairItem mStoredFastPairItem;
- @Mock
- Data.FastPairDeviceWithAccountKey mFastPairDeviceWithAccountKey;
- private static final byte[] ACCOUNT_KEY = new byte[] {0, 1, 2};
+ @Mock private Clock mClock;
+
+ private final Account mAccount = new Account("test1@gmail.com", "com.google");
+ private static final byte[] ACCOUNT_KEY =
+ new byte[] {4, 65, 90, -26, -5, -38, -128, 40, -103, 101, 95, 55, 8, -42, -120, 78};
+ private static final byte[] ACCOUNT_KEY_2 = new byte[] {0, 1, 2};
private static final String BLUETOOTH_ADDRESS = "AA:BB:CC:DD";
+ private static final String MODEL_ID = "MODEL_ID";
private static final int CLOSE_RSSI = -80;
private static final int FAR_AWAY_RSSI = -120;
private static final int TX_POWER = -70;
private static final byte[] INITIAL_BYTE_ARRAY = new byte[]{0x01, 0x02, 0x03};
+ private static final byte[] SUBSEQUENT_DATA_BYTES = new byte[]{
+ 0, -112, -63, 32, 37, -20, 36, 0, -60, 0, -96, 17, -10, 51, -28, -28, 100};
+ private static final byte[] SUBSEQUENT_DATA_BYTES_INVALID = new byte[]{
+ 0, -112, -63, 32, 37, -20, 48, 0, -60, 0, 90, 17, -10, 51, -28, -28, 100};
private static final byte[] SALT = new byte[]{0x01};
+ private static final Cache.StoredDiscoveryItem STORED_DISCOVERY_ITEM =
+ Cache.StoredDiscoveryItem.newBuilder()
+ .setDeviceName("Device Name")
+ .setTxPower(TX_POWER)
+ .setMacAddress(BLUETOOTH_ADDRESS)
+ .build();
LocatorContextWrapper mLocatorContextWrapper;
FastPairAdvHandler mFastPairAdvHandler;
@@ -83,8 +108,29 @@
mLocatorContextWrapper.getLocator().overrideBindingForTest(
FastPairNotificationManager.class, mFastPairNotificationManager
);
+ mLocatorContextWrapper.getLocator().overrideBindingForTest(
+ FastPairCacheManager.class, mFastPairCacheManager
+ );
+ mLocatorContextWrapper.getLocator().overrideBindingForTest(
+ FastPairController.class, mFastPairController);
+ mLocatorContextWrapper.getLocator().overrideBindingForTest(Clock.class, mClock);
+
when(mFastPairDataProvider.loadFastPairAntispoofKeyDeviceMetadata(any()))
.thenReturn(Rpcs.GetObservedDeviceResponse.getDefaultInstance());
+ when(mFastPairDataProvider.loadFastPairEligibleAccounts()).thenReturn(List.of(mAccount));
+ when(mFastPairDataProvider.loadFastPairDeviceWithAccountKey(mAccount))
+ .thenReturn(List.of(mFastPairDeviceWithAccountKey));
+ when(mFastPairDataProvider.loadFastPairDeviceWithAccountKey(eq(mAccount), any()))
+ .thenReturn(List.of(mFastPairDeviceWithAccountKey));
+ when(mFastPairDeviceWithAccountKey.getAccountKey())
+ .thenReturn(ByteString.copyFrom(ACCOUNT_KEY));
+ when(mFastPairDeviceWithAccountKey.getDiscoveryItem())
+ .thenReturn(STORED_DISCOVERY_ITEM);
+ when(mStoredFastPairItem.getAccountKey())
+ .thenReturn(ByteString.copyFrom(ACCOUNT_KEY_2), ByteString.copyFrom(ACCOUNT_KEY_2));
+ when(mFastPairCacheManager.getAllSavedStoredFastPairItem())
+ .thenReturn(List.of(mStoredFastPairItem));
+
mFastPairAdvHandler = new FastPairAdvHandler(mLocatorContextWrapper, mFastPairDataProvider);
}
@@ -93,6 +139,7 @@
FastPairDevice fastPairDevice = new FastPairDevice.Builder()
.setData(INITIAL_BYTE_ARRAY)
.setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setModelId(MODEL_ID)
.setRssi(CLOSE_RSSI)
.setTxPower(TX_POWER)
.build();
@@ -107,6 +154,7 @@
FastPairDevice fastPairDevice = new FastPairDevice.Builder()
.setData(INITIAL_BYTE_ARRAY)
.setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setModelId(MODEL_ID)
.setRssi(FAR_AWAY_RSSI)
.setTxPower(TX_POWER)
.build();
@@ -117,37 +165,68 @@
}
@Test
- public void testSubsequentBroadcast_notShowHalfSheet() {
- byte[] fastPairRecordWithBloomFilter =
- new byte[]{
- (byte) 0x02,
- (byte) 0x01,
- (byte) 0x02, // Flags
- (byte) 0x02,
- (byte) 0x0A,
- (byte) 0xEB, // Tx Power (-20)
- (byte) 0x0B,
- (byte) 0x16,
- (byte) 0x2C,
- (byte) 0xFE, // FastPair Service Data
- (byte) 0x00, // Flags (model ID length = 3)
- (byte) 0x40, // Account key hash flags (length = 4, type = 0)
- (byte) 0x11,
- (byte) 0x22,
- (byte) 0x33,
- (byte) 0x44, // Account key hash (0x11223344)
- (byte) 0x11, // Account key salt flags (length = 1, type = 1)
- (byte) 0x55, // Account key salt
- };
+ public void testSubsequentBroadcast_showNotification() {
FastPairDevice fastPairDevice = new FastPairDevice.Builder()
- .setData(fastPairRecordWithBloomFilter)
+ .setData(SUBSEQUENT_DATA_BYTES)
.setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setModelId(MODEL_ID)
.setRssi(CLOSE_RSSI)
.setTxPower(TX_POWER)
.build();
-
mFastPairAdvHandler.handleBroadcast(fastPairDevice);
+ DiscoveryItem discoveryItem =
+ new DiscoveryItem(mLocatorContextWrapper, STORED_DISCOVERY_ITEM);
+ verify(mFastPairNotificationManager).showDiscoveryNotification(eq(discoveryItem),
+ eq(ACCOUNT_KEY));
+ verify(mFastPairHalfSheetManager, never()).showHalfSheet(any());
+ }
+
+ @Test
+ public void testSubsequentBroadcast_tooFar_notShowNotification() {
+ FastPairDevice fastPairDevice = new FastPairDevice.Builder()
+ .setData(SUBSEQUENT_DATA_BYTES)
+ .setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setModelId(MODEL_ID)
+ .setRssi(FAR_AWAY_RSSI)
+ .setTxPower(TX_POWER)
+ .build();
+ mFastPairAdvHandler.handleBroadcast(fastPairDevice);
+
+ verify(mFastPairController, never()).pair(any(), any(), any());
+ verify(mFastPairHalfSheetManager, never()).showHalfSheet(any());
+ }
+
+ @Test
+ public void testSubsequentBroadcast_notRecognize_notShowNotification() {
+ FastPairDevice fastPairDevice = new FastPairDevice.Builder()
+ .setData(SUBSEQUENT_DATA_BYTES_INVALID)
+ .setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setModelId(MODEL_ID)
+ .setRssi(FAR_AWAY_RSSI)
+ .setTxPower(TX_POWER)
+ .build();
+ mFastPairAdvHandler.handleBroadcast(fastPairDevice);
+
+ verify(mFastPairController, never()).pair(any(), any(), any());
+ verify(mFastPairHalfSheetManager, never()).showHalfSheet(any());
+ }
+
+ @Test
+ public void testSubsequentBroadcast_cached_notShowNotification() {
+ when(mStoredFastPairItem.getAccountKey())
+ .thenReturn(ByteString.copyFrom(ACCOUNT_KEY), ByteString.copyFrom(ACCOUNT_KEY));
+
+ FastPairDevice fastPairDevice = new FastPairDevice.Builder()
+ .setData(SUBSEQUENT_DATA_BYTES_INVALID)
+ .setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setModelId(MODEL_ID)
+ .setRssi(FAR_AWAY_RSSI)
+ .setTxPower(TX_POWER)
+ .build();
+ mFastPairAdvHandler.handleBroadcast(fastPairDevice);
+
+ verify(mFastPairController, never()).pair(any(), any(), any());
verify(mFastPairHalfSheetManager, never()).showHalfSheet(any());
}
@@ -190,4 +269,12 @@
assertThat(FastPairAdvHandler.findRecognizedDeviceFromCachedItem(
ImmutableList.of(mStoredFastPairItem), mBloomFilter, SALT)).isNotNull();
}
+
+ @Test
+ public void testGenerateBatteryData_correct() {
+ byte[] data = new byte[]
+ {0, -112, 96, 5, -125, 45, 35, 98, 98, 81, 13, 17, 3, 51, -28, -28, -28};
+ assertThat(FastPairAdvHandler.generateBatteryData(data))
+ .isEqualTo(new byte[]{51, -28, -28, -28});
+ }
}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java
index 26d1847..00df1b9 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java
@@ -17,6 +17,7 @@
package com.android.server.nearby.fastpair;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -54,7 +55,7 @@
public void testFastPairInit() {
mFastPairManager.initiate();
- verify(mContext, times(1)).registerReceiver(any(), any());
+ verify(mContext, times(1)).registerReceiver(any(), any(), anyInt());
}
@Test
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetBlocklistTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetBlocklistTest.java
new file mode 100644
index 0000000..f3afbe7
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetBlocklistTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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 com.android.server.nearby.fastpair.halfsheet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import com.android.server.nearby.fastpair.blocklist.Blocklist;
+import com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState;
+import com.android.server.nearby.fastpair.blocklist.BlocklistElement;
+import com.android.server.nearby.util.DefaultClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FastPairHalfSheetBlocklistTest {
+
+ @Mock
+ private DefaultClock mClock;
+ private FastPairHalfSheetBlocklist mFastPairHalfSheetBlocklist;
+ private static final int SIZE_OF_BLOCKLIST = 2;
+ private static final long CURRENT_TIME = 1000000L;
+ private static final long BLOCKLIST_CANCEL_TIMEOUT_MILLIS = 30000L;
+ private static final long SUPPRESS_ALL_DURATION_MILLIS = 60000L;
+ private static final long DURATION_RESURFACE_DISMISS_HALF_SHEET_MILLISECOND = 86400000;
+ private static final long STATE_EXPIRATION_MILLISECOND = 86400000;
+ private static final int HALFSHEET_ID = 1;
+ private static final long DURATION_MILLI_SECONDS_LONG = 86400000;
+ private static final int DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS = 1;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mClock.elapsedRealtime()).thenReturn(CURRENT_TIME);
+ mFastPairHalfSheetBlocklist = new FastPairHalfSheetBlocklist(SIZE_OF_BLOCKLIST, mClock);
+ }
+
+ @Test
+ public void testUpdateState() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.ACTIVE, CURRENT_TIME));
+
+ boolean initiallyBlocklisted =
+ mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS);
+
+ mFastPairHalfSheetBlocklist.updateState(HALFSHEET_ID, Blocklist.BlocklistState.ACTIVE);
+ boolean isBlockListedWhenActive =
+ mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS);
+
+ mFastPairHalfSheetBlocklist.updateState(HALFSHEET_ID, Blocklist.BlocklistState.DISMISSED);
+ boolean isBlockListedAfterDismissed =
+ mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS);
+
+ mFastPairHalfSheetBlocklist.updateState(HALFSHEET_ID,
+ Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN);
+ boolean isBlockListedAfterDoNotShowAgain =
+ mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS);
+
+ mFastPairHalfSheetBlocklist.updateState(HALFSHEET_ID,
+ Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN_LONG);
+ boolean isBlockListedAfterDoNotShowAgainLong =
+ mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS);
+
+ assertThat(initiallyBlocklisted).isFalse();
+ assertThat(isBlockListedWhenActive).isFalse();
+ assertThat(isBlockListedAfterDismissed).isTrue();
+ assertThat(isBlockListedAfterDoNotShowAgain).isTrue();
+ assertThat(isBlockListedAfterDoNotShowAgainLong).isTrue();
+ }
+
+ @Test
+ public void testBlocklist_overflow() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DISMISSED, CURRENT_TIME));
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID + 1,
+ new BlocklistElement(Blocklist.BlocklistState.UNKNOWN, CURRENT_TIME));
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID + 2,
+ new BlocklistElement(Blocklist.BlocklistState.UNKNOWN, CURRENT_TIME));
+
+ // blocklist should have evicted HALFSHEET_ID making it no longer blocklisted, this is
+ // because for the test we initialize the size of the blocklist cache to be max = 2
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+
+ @Test
+ public void removeHalfSheetDismissState() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DISMISSED, CURRENT_TIME));
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ assertThat(mFastPairHalfSheetBlocklist.removeBlocklist(HALFSHEET_ID)).isTrue();
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ assertThat(mFastPairHalfSheetBlocklist.removeBlocklist(HALFSHEET_ID + 1)).isFalse();
+ }
+
+ @Test
+ public void removeHalfSheetBanState() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ assertThat(mFastPairHalfSheetBlocklist.removeBlocklist(HALFSHEET_ID)).isTrue();
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ assertThat(mFastPairHalfSheetBlocklist.removeBlocklist(HALFSHEET_ID + 1)).isFalse();
+ }
+
+ @Test
+ public void testHalfSheetTimeOutReleaseBan() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ when(mClock.elapsedRealtime())
+ .thenReturn(CURRENT_TIME + BLOCKLIST_CANCEL_TIMEOUT_MILLIS + 1);
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+
+ @Test
+ public void testHalfSheetDoNotShowAgainLong() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(
+ Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN_LONG, CURRENT_TIME));
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ assertThat(mFastPairHalfSheetBlocklist.removeBlocklist(HALFSHEET_ID)).isTrue();
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ assertThat(mFastPairHalfSheetBlocklist.removeBlocklist(HALFSHEET_ID + 1)).isFalse();
+ }
+
+ @Test
+ public void testHalfSheetDoNotShowAgainLongTimeout() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ when(mClock.elapsedRealtime()).thenReturn(CURRENT_TIME + DURATION_MILLI_SECONDS_LONG + 1);
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+
+ @Test
+ public void banAllItem_blockHalfSheet() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.ACTIVE, CURRENT_TIME));
+
+ mFastPairHalfSheetBlocklist.banAllItem(SUPPRESS_ALL_DURATION_MILLIS);
+ when(mClock.elapsedRealtime()).thenReturn(CURRENT_TIME + SUPPRESS_ALL_DURATION_MILLIS - 1);
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ }
+
+ @Test
+ public void banAllItem_invokeAgainWithShorterDurationTime_blockHalfSheet() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.ACTIVE, CURRENT_TIME));
+
+ mFastPairHalfSheetBlocklist.banAllItem(SUPPRESS_ALL_DURATION_MILLIS);
+ // The 2nd invocation time is shorter than the original one so it's ignored.
+ mFastPairHalfSheetBlocklist.banAllItem(SUPPRESS_ALL_DURATION_MILLIS - 1);
+ when(mClock.elapsedRealtime()).thenReturn(CURRENT_TIME + SUPPRESS_ALL_DURATION_MILLIS - 1);
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ }
+
+ @Test
+ public void banAllItem_releaseHalfSheet() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.ACTIVE, CURRENT_TIME));
+
+ mFastPairHalfSheetBlocklist.banAllItem(SUPPRESS_ALL_DURATION_MILLIS);
+ when(mClock.elapsedRealtime()).thenReturn(CURRENT_TIME + SUPPRESS_ALL_DURATION_MILLIS);
+
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+
+ @Test
+ public void banAllItem_extendEndTime_blockHalfSheet() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.ACTIVE, CURRENT_TIME));
+
+ mFastPairHalfSheetBlocklist.banAllItem(SUPPRESS_ALL_DURATION_MILLIS);
+ when(mClock.elapsedRealtime()).thenReturn(CURRENT_TIME + SUPPRESS_ALL_DURATION_MILLIS);
+ // Another banAllItem comes so the end time is extended.
+ mFastPairHalfSheetBlocklist.banAllItem(/* banDurationTimeMillis= */ 1);
+
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ }
+
+ @Test
+ public void testHalfSheetTimeOutFirstDismissWithInDuration() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ when(mClock.elapsedRealtime())
+ .thenReturn(CURRENT_TIME + DURATION_RESURFACE_DISMISS_HALF_SHEET_MILLISECOND - 1);
+
+ assertThat(
+ mFastPairHalfSheetBlocklist.isBlocklisted(
+ HALFSHEET_ID, (int) DURATION_RESURFACE_DISMISS_HALF_SHEET_MILLISECOND))
+ .isTrue();
+ }
+
+ @Test
+ public void testHalfSheetTimeOutFirstDismissOutOfDuration() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ when(mClock.elapsedRealtime())
+ .thenReturn(CURRENT_TIME + DURATION_RESURFACE_DISMISS_HALF_SHEET_MILLISECOND + 1);
+
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+
+ @Test
+ public void testHalfSheetReset() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ mFastPairHalfSheetBlocklist.resetBlockState(HALFSHEET_ID);
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+
+ @Test
+ public void testIsStateExpired() {
+ mFastPairHalfSheetBlocklist.put(
+ HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ when(mClock.elapsedRealtime())
+ .thenReturn(CURRENT_TIME + 1);
+ assertThat(mFastPairHalfSheetBlocklist.isStateExpired(HALFSHEET_ID)).isFalse();
+ when(mClock.elapsedRealtime())
+ .thenReturn(CURRENT_TIME + STATE_EXPIRATION_MILLISECOND + 1);
+ assertThat(mFastPairHalfSheetBlocklist.isStateExpired(HALFSHEET_ID)).isTrue();
+ }
+
+ @Test
+ public void testForceUpdateState() {
+ mFastPairHalfSheetBlocklist.put(HALFSHEET_ID,
+ new BlocklistElement(Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN, CURRENT_TIME));
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isTrue();
+ mFastPairHalfSheetBlocklist.forceUpdateState(HALFSHEET_ID, BlocklistState.ACTIVE);
+ assertThat(mFastPairHalfSheetBlocklist.isBlocklisted(HALFSHEET_ID,
+ DURATION_RESURFACE_HALFSHEET_FIRST_DISMISS_MILLI_SECONDS)).isFalse();
+ }
+}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManagerTest.java
index b51a295..82b9070 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManagerTest.java
@@ -16,14 +16,23 @@
package com.android.server.nearby.fastpair.halfsheet;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.ACTIVE;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.DISMISSED;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN;
+import static com.android.server.nearby.fastpair.blocklist.Blocklist.BlocklistState.DO_NOT_SHOW_AGAIN_LONG;
+import static com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager.DISMISS_HALFSHEET_RUNNABLE_NAME;
+import static com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager.SHOW_TOAST_RUNNABLE_NAME;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -33,10 +42,14 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.nearby.FastPairStatusCallback;
+import android.nearby.PairStatusMetadata;
import android.os.UserHandle;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.server.nearby.common.eventloop.EventLoop;
+import com.android.server.nearby.common.eventloop.NamedRunnable;
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
import com.android.server.nearby.fastpair.FastPairController;
@@ -53,11 +66,22 @@
import service.proto.Cache;
public class FastPairHalfSheetManagerTest {
- private static final String BLEADDRESS = "11:22:44:66";
+ private static final String MODEL_ID = "model_id";
+ private static final String BLE_ADDRESS = "11:22:44:66";
+ private static final String MODEL_ID_1 = "model_id_1";
+ private static final String BLE_ADDRESS_1 = "99:99:99:99";
private static final String NAME = "device_name";
private static final int PASSKEY = 1234;
+ private static final int SUCCESS = 1001;
+ private static final int FAIL = 1002;
+ private static final String EXTRA_HALF_SHEET_CONTENT =
+ "com.android.nearby.halfsheet.HALF_SHEET_CONTENT";
+ private static final String RESULT_FAIL = "RESULT_FAIL";
private FastPairHalfSheetManager mFastPairHalfSheetManager;
private Cache.ScanFastPairStoreItem mScanFastPairStoreItem;
+ private ResolveInfo mResolveInfo;
+ private List<ResolveInfo> mResolveInfoList;
+ private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
@Mock
LocatorContextWrapper mContextWrapper;
@@ -67,40 +91,42 @@
Locator mLocator;
@Mock
FastPairController mFastPairController;
+ @Mock
+ EventLoop mEventLoop;
+ @Mock
+ FastPairStatusCallback mFastPairStatusCallback;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mLocator.overrideBindingForTest(FastPairController.class, mFastPairController);
+ mLocator.overrideBindingForTest(EventLoop.class, mEventLoop);
+
+ mResolveInfo = new ResolveInfo();
+ mResolveInfoList = new ArrayList<>();
+ mResolveInfo.activityInfo = new ActivityInfo();
+ mApplicationInfo = new ApplicationInfo();
+ mPackageManager = mock(PackageManager.class);
+
when(mContext.getContentResolver()).thenReturn(
InstrumentationRegistry.getInstrumentation().getContext().getContentResolver());
+ when(mContextWrapper.getPackageManager()).thenReturn(mPackageManager);
+ when(mContextWrapper.getLocator()).thenReturn(mLocator);
+ when(mLocator.get(EventLoop.class)).thenReturn(mEventLoop);
+ when(mPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(mResolveInfoList);
+ when(mPackageManager.canRequestPackageInstalls()).thenReturn(false);
+
mScanFastPairStoreItem = Cache.ScanFastPairStoreItem.newBuilder()
- .setAddress(BLEADDRESS)
+ .setModelId(MODEL_ID)
+ .setAddress(BLE_ADDRESS)
.setDeviceName(NAME)
.build();
}
@Test
public void verifyFastPairHalfSheetManagerBehavior() {
- mLocator.overrideBindingForTest(FastPairController.class, mFastPairController);
- ResolveInfo resolveInfo = new ResolveInfo();
- List<ResolveInfo> resolveInfoList = new ArrayList<>();
-
- mPackageManager = mock(PackageManager.class);
- when(mContextWrapper.getPackageManager()).thenReturn(mPackageManager);
- resolveInfo.activityInfo = new ActivityInfo();
- ApplicationInfo applicationInfo = new ApplicationInfo();
- applicationInfo.sourceDir = "/apex/com.android.tethering";
- applicationInfo.packageName = "test.package";
- resolveInfo.activityInfo.applicationInfo = applicationInfo;
- resolveInfoList.add(resolveInfo);
- when(mPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(resolveInfoList);
- when(mPackageManager.canRequestPackageInstalls()).thenReturn(false);
-
- mFastPairHalfSheetManager =
- new FastPairHalfSheetManager(mContextWrapper);
-
- when(mContextWrapper.getLocator()).thenReturn(mLocator);
-
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
@@ -111,27 +137,12 @@
@Test
public void verifyFastPairHalfSheetManagerHalfSheetApkNotValidBehavior() {
- mLocator.overrideBindingForTest(FastPairController.class, mFastPairController);
- ResolveInfo resolveInfo = new ResolveInfo();
- List<ResolveInfo> resolveInfoList = new ArrayList<>();
-
- mPackageManager = mock(PackageManager.class);
- when(mContextWrapper.getPackageManager()).thenReturn(mPackageManager);
- resolveInfo.activityInfo = new ActivityInfo();
- ApplicationInfo applicationInfo = new ApplicationInfo();
// application directory is wrong
- applicationInfo.sourceDir = "/apex/com.android.nearby";
- applicationInfo.packageName = "test.package";
- resolveInfo.activityInfo.applicationInfo = applicationInfo;
- resolveInfoList.add(resolveInfo);
- when(mPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(resolveInfoList);
- when(mPackageManager.canRequestPackageInstalls()).thenReturn(false);
-
- mFastPairHalfSheetManager =
- new FastPairHalfSheetManager(mContextWrapper);
-
- when(mContextWrapper.getLocator()).thenReturn(mLocator);
-
+ mApplicationInfo.sourceDir = "/apex/com.android.nearby";
+ mApplicationInfo.packageName = "test.package";
+ mResolveInfo.activityInfo.applicationInfo = mApplicationInfo;
+ mResolveInfoList.add(mResolveInfo);
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
@@ -141,22 +152,418 @@
}
@Test
- public void getHalfSheetForegroundState() {
+ public void testHalfSheetForegroundState() {
+ configResolveInfoList();
mFastPairHalfSheetManager =
new FastPairHalfSheetManager(mContextWrapper);
- assertThat(mFastPairHalfSheetManager.getHalfSheetForegroundState()).isTrue();
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ assertThat(mFastPairHalfSheetManager.getHalfSheetForeground()).isTrue();
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+ assertThat(mFastPairHalfSheetManager.getHalfSheetForeground()).isFalse();
}
@Test
public void testEmptyMethods() {
- mFastPairHalfSheetManager =
- new FastPairHalfSheetManager(mContextWrapper);
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
mFastPairHalfSheetManager.destroyBluetoothPairController();
- mFastPairHalfSheetManager.disableDismissRunnable();
- mFastPairHalfSheetManager.notifyPairingProcessDone(true, BLEADDRESS, null);
+ mFastPairHalfSheetManager.notifyPairingProcessDone(true, BLE_ADDRESS, null);
mFastPairHalfSheetManager.showPairingFailed();
mFastPairHalfSheetManager.showPairingHalfSheet(null);
- mFastPairHalfSheetManager.showPairingSuccessHalfSheet(BLEADDRESS);
+ mFastPairHalfSheetManager.showPairingSuccessHalfSheet(BLE_ADDRESS);
mFastPairHalfSheetManager.showPasskeyConfirmation(null, PASSKEY);
}
+
+ @Test
+ public void showInitialPairingHalfSheetThenDismissOnce_stateDISMISSED() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ //First time dismiss -> state: DISMISSED
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState()).isEqualTo(DISMISSED);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheetThenBan_stateDO_NOT_SHOW_AGAIN() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ //First time ban -> state: DO_NOT_SHOW_AGAIN
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState()).isEqualTo(DO_NOT_SHOW_AGAIN);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheetThenBanTwice_stateDO_NOT_SHOW_AGAIN_LONG() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+ mFastPairHalfSheetManager.dismiss(MODEL_ID);
+
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ //Second time ban -> state: DO_NOT_SHOW_AGAIN
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState())
+ .isEqualTo(DO_NOT_SHOW_AGAIN_LONG);
+ }
+
+ @Test
+ public void testResetBanSate_resetDISMISSEDtoACTIVE() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ mHalfSheetBlocklist.updateState(halfSheetId, DISMISSED);
+ mFastPairHalfSheetManager.resetBanState(MODEL_ID);
+
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState()).isEqualTo(ACTIVE);
+ }
+
+ @Test
+ public void testResetBanSate_resetDO_NOT_SHOW_AGAINtoACTIVE() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ mHalfSheetBlocklist.updateState(halfSheetId, DO_NOT_SHOW_AGAIN);
+ mFastPairHalfSheetManager.resetBanState(MODEL_ID);
+
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState()).isEqualTo(ACTIVE);
+ }
+
+ @Test
+ public void testResetBanSate_resetDO_NOT_SHOW_AGAIN_LONGtoACTIVE() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ mHalfSheetBlocklist.updateState(halfSheetId, DO_NOT_SHOW_AGAIN_LONG
+ );
+ mFastPairHalfSheetManager.resetBanState(MODEL_ID);
+
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState()).isEqualTo(ACTIVE);
+ }
+
+ @Test
+ public void testReportDonePairing() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ assertThat(mFastPairHalfSheetManager.getHalfSheetBlocklist().size()).isEqualTo(1);
+
+ mFastPairHalfSheetManager
+ .reportDonePairing(mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID));
+
+ assertThat(mFastPairHalfSheetManager.getHalfSheetBlocklist().size()).isEqualTo(0);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_AutoDismiss() throws InterruptedException {
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ verifyInitialPairingNameRunnablePostedTimes(1);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_whenUiShownAndItemWithTheSameAddress() {
+ Cache.ScanFastPairStoreItem testItem = Cache.ScanFastPairStoreItem.newBuilder()
+ .setModelId(MODEL_ID)
+ .setAddress(BLE_ADDRESS)
+ .setDeviceName(NAME)
+ .build();
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ verifyHalfSheetActivityIntent(1);
+ verifyInitialPairingNameRunnablePostedTimes(1);
+
+ mFastPairHalfSheetManager.showHalfSheet(testItem);
+ // When half sheet shown and receives broadcast from the same address,
+ // DO NOT request start-activity to avoid unnecessary memory usage,
+ // Just reset the auto dismiss timeout for the new request
+ verifyHalfSheetActivityIntent(1);
+ verifyInitialPairingNameRunnablePostedTimes(2);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_whenUiShowAndItemWithDifferentAddressSameModelId() {
+ Cache.ScanFastPairStoreItem testItem = Cache.ScanFastPairStoreItem.newBuilder()
+ .setModelId(MODEL_ID)
+ .setAddress(BLE_ADDRESS_1)
+ .setDeviceName(NAME)
+ .build();
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ verifyHalfSheetActivityIntent(1);
+ verifyInitialPairingNameRunnablePostedTimes(1);
+
+ mFastPairHalfSheetManager.showHalfSheet(testItem);
+ // When half sheet shown and receives broadcast from the same model id
+ // but with different address, DO NOT rest the auto dismiss timeout. No action is required.
+ verifyHalfSheetActivityIntent(1);
+ verifyInitialPairingNameRunnablePostedTimes(1);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_whenUiShowAndItemWithDifferentModelId() {
+ Cache.ScanFastPairStoreItem testItem = Cache.ScanFastPairStoreItem.newBuilder()
+ .setModelId(MODEL_ID_1)
+ .setAddress(BLE_ADDRESS_1)
+ .setDeviceName(NAME)
+ .build();
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+
+ verifyInitialPairingNameRunnablePostedTimes(1);
+ verifyHalfSheetActivityIntent(1);
+
+ mFastPairHalfSheetManager.showHalfSheet(testItem);
+ // When half sheet shown and receives broadcast from a different model id,
+ // the new request should be ignored. No action is required.
+ verifyHalfSheetActivityIntent(1);
+ verifyInitialPairingNameRunnablePostedTimes(1);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_whenUiNotShownAndIsPairingWithTheSameAddress() {
+ Cache.ScanFastPairStoreItem testItem = Cache.ScanFastPairStoreItem.newBuilder()
+ .setModelId(MODEL_ID)
+ .setAddress(BLE_ADDRESS)
+ .setDeviceName(NAME)
+ .build();
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.setHalfSheetForeground(/* state= */ false);
+ mFastPairHalfSheetManager.setIsActivePairing(true);
+ mFastPairHalfSheetManager.showHalfSheet(testItem);
+
+ // If the half sheet is not in foreground but the system is still pairing the same device,
+ // mark as duplicate request and skip.
+ verifyHalfSheetActivityIntent(1);
+ verifyInitialPairingNameRunnablePostedTimes(1);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_whenUiNotShownAndIsPairingWithADifferentAddress() {
+ Cache.ScanFastPairStoreItem testItem = Cache.ScanFastPairStoreItem.newBuilder()
+ .setModelId(MODEL_ID_1)
+ .setAddress(BLE_ADDRESS_1)
+ .setDeviceName(NAME)
+ .build();
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.setHalfSheetForeground(/* state= */ false);
+ mFastPairHalfSheetManager.setIsActivePairing(true);
+ mFastPairHalfSheetManager.showHalfSheet(testItem);
+
+ // shouldShowHalfSheet
+ verifyHalfSheetActivityIntent(2);
+ verifyInitialPairingNameRunnablePostedTimes(2);
+ }
+
+ @Test
+ public void showInitialPairingHalfSheet_whenUiNotShownAndIsNotPairingWithTheSameAddress() {
+ Cache.ScanFastPairStoreItem testItem = Cache.ScanFastPairStoreItem.newBuilder()
+ .setModelId(MODEL_ID)
+ .setAddress(BLE_ADDRESS)
+ .setDeviceName(NAME)
+ .build();
+ configResolveInfoList();
+ mFastPairHalfSheetManager =
+ new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.setHalfSheetForeground(/* state= */ false);
+ mFastPairHalfSheetManager.setIsActivePairing(false);
+ mFastPairHalfSheetManager.showHalfSheet(testItem);
+
+ // shouldShowHalfSheet
+ verifyHalfSheetActivityIntent(2);
+ verifyInitialPairingNameRunnablePostedTimes(2);
+ }
+
+ @Test
+ public void testReportActivelyPairing() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+
+ assertThat(mFastPairHalfSheetManager.isActivePairing()).isFalse();
+
+ mFastPairHalfSheetManager.reportActivelyPairing();
+
+ assertThat(mFastPairHalfSheetManager.isActivePairing()).isTrue();
+ }
+
+ @Test
+ public void showPairingSuccessHalfSheetHalfSheetActivityActive_ChangeUIToShowSuccessInfo() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ mFastPairHalfSheetManager.mFastPairUiService
+ .setFastPairStatusCallback(mFastPairStatusCallback);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.showPairingSuccessHalfSheet(BLE_ADDRESS);
+
+ verifyFastPairStatusCallback(1, SUCCESS);
+ assertThat(mFastPairHalfSheetManager.isActivePairing()).isFalse();
+ }
+
+ @Test
+ public void showPairingSuccessHalfSheetHalfSheetActivityNotActive_showToast() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.setHalfSheetForeground(false);
+ mFastPairHalfSheetManager.showPairingSuccessHalfSheet(BLE_ADDRESS);
+
+ ArgumentCaptor<NamedRunnable> captor = ArgumentCaptor.forClass(NamedRunnable.class);
+
+ verify(mEventLoop).postRunnable(captor.capture());
+ assertThat(
+ captor.getAllValues().stream()
+ .filter(r -> r.name.equals(SHOW_TOAST_RUNNABLE_NAME))
+ .count())
+ .isEqualTo(1);
+ assertThat(mFastPairHalfSheetManager.isActivePairing()).isFalse();
+ }
+
+ @Test
+ public void showPairingFailedHalfSheetHalfSheetActivityActive_ChangeUIToShowFailedInfo() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ mFastPairHalfSheetManager.mFastPairUiService
+ .setFastPairStatusCallback(mFastPairStatusCallback);
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.showPairingFailed();
+
+ verifyFastPairStatusCallback(1, FAIL);
+ assertThat(mFastPairHalfSheetManager.isActivePairing()).isFalse();
+ }
+
+ @Test
+ public void showPairingFailedHalfSheetActivityNotActive_StartHalfSheetToShowFailedInfo() {
+ configResolveInfoList();
+ mFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ FastPairHalfSheetBlocklist mHalfSheetBlocklist =
+ mFastPairHalfSheetManager.getHalfSheetBlocklist();
+
+ mFastPairHalfSheetManager.showHalfSheet(mScanFastPairStoreItem);
+ mFastPairHalfSheetManager.setHalfSheetForeground(false);
+ mFastPairHalfSheetManager.showPairingFailed();
+
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ Integer halfSheetId = mFastPairHalfSheetManager.mModelIdMap.get(MODEL_ID);
+
+ verify(mContextWrapper, times(2))
+ .startActivityAsUser(captor.capture(), eq(UserHandle.CURRENT));
+ assertThat(
+ captor.getAllValues().stream()
+ .filter(r ->
+ r.getStringExtra(EXTRA_HALF_SHEET_CONTENT) != null
+ && r.getStringExtra(EXTRA_HALF_SHEET_CONTENT)
+ .equals(RESULT_FAIL))
+
+ .count())
+ .isEqualTo(1);
+ assertThat(mFastPairHalfSheetManager.isActivePairing()).isFalse();
+ assertThat(mHalfSheetBlocklist.get(halfSheetId).getState()).isEqualTo(ACTIVE);
+ }
+
+ private void verifyInitialPairingNameRunnablePostedTimes(int times) {
+ ArgumentCaptor<NamedRunnable> captor = ArgumentCaptor.forClass(NamedRunnable.class);
+
+ verify(mEventLoop, times(times)).postRunnableDelayed(captor.capture(), anyLong());
+ assertThat(
+ captor.getAllValues().stream()
+ .filter(r -> r.name.equals(DISMISS_HALFSHEET_RUNNABLE_NAME))
+ .count())
+ .isEqualTo(times);
+ }
+
+ private void verifyHalfSheetActivityIntent(int times) {
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+
+ verify(mContextWrapper, times(times))
+ .startActivityAsUser(captor.capture(), eq(UserHandle.CURRENT));
+ assertThat(
+ captor.getAllValues().stream()
+ .filter(r -> r.getAction().equals("android.nearby.SHOW_HALFSHEET"))
+ .count())
+ .isEqualTo(times);
+ }
+
+ private void verifyFastPairStatusCallback(int times, int status) {
+ ArgumentCaptor<PairStatusMetadata> captor =
+ ArgumentCaptor.forClass(PairStatusMetadata.class);
+ verify(mFastPairStatusCallback, times(times)).onPairUpdate(any(), captor.capture());
+ assertThat(
+ captor.getAllValues().stream()
+ .filter(r -> r.getStatus() == status)
+ .count())
+ .isEqualTo(times);
+ }
+
+ private void configResolveInfoList() {
+ mApplicationInfo.sourceDir = "/apex/com.android.tethering";
+ mApplicationInfo.packageName = "test.package";
+ mResolveInfo.activityInfo.applicationInfo = mApplicationInfo;
+ mResolveInfoList.add(mResolveInfo);
+ }
}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationBuilderTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationBuilderTest.java
new file mode 100644
index 0000000..d995969
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationBuilderTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 com.android.server.nearby.fastpair.notification;
+
+import static com.android.server.nearby.fastpair.notification.FastPairNotificationBuilder.NOTIFICATION_OVERRIDE_NAME_EXTRA;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.nearby.halfsheet.R;
+import com.android.server.nearby.fastpair.HalfSheetResources;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FastPairNotificationBuilderTest {
+
+ private static final String STRING_DEVICE = "Devices";
+ private static final String STRING_NEARBY = "Nearby";
+
+ @Mock private Context mContext;
+ @Mock private PackageManager mPackageManager;
+ @Mock private Resources mResources;
+
+ private ResolveInfo mResolveInfo;
+ private List<ResolveInfo> mResolveInfoList;
+ private ApplicationInfo mApplicationInfo;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ HalfSheetResources.setResourcesContextForTest(mContext);
+
+ mResolveInfo = new ResolveInfo();
+ mResolveInfoList = new ArrayList<>();
+ mResolveInfo.activityInfo = new ActivityInfo();
+ mApplicationInfo = new ApplicationInfo();
+
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mContext.getApplicationInfo())
+ .thenReturn(InstrumentationRegistry
+ .getInstrumentation().getContext().getApplicationInfo());
+ when(mContext.getContentResolver()).thenReturn(
+ InstrumentationRegistry.getInstrumentation().getContext().getContentResolver());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(mResolveInfoList);
+ when(mPackageManager.canRequestPackageInstalls()).thenReturn(false);
+ mApplicationInfo.sourceDir = "/apex/com.android.nearby";
+ mApplicationInfo.packageName = "test.package";
+ mResolveInfo.activityInfo.applicationInfo = mApplicationInfo;
+ mResolveInfoList.add(mResolveInfo);
+
+ when(mResources.getString(eq(R.string.common_devices))).thenReturn(STRING_DEVICE);
+ when(mResources.getString(eq(R.string.common_nearby_title))).thenReturn(STRING_NEARBY);
+ }
+
+ @Test
+ public void setIsDevice_true() {
+ Notification notification =
+ new FastPairNotificationBuilder(mContext, "channelId")
+ .setIsDevice(true).build();
+ assertThat(notification.extras.getString(NOTIFICATION_OVERRIDE_NAME_EXTRA))
+ .isEqualTo(STRING_DEVICE);
+ }
+
+ @Test
+ public void setIsDevice_false() {
+ Notification notification =
+ new FastPairNotificationBuilder(mContext, "channelId")
+ .setIsDevice(false).build();
+ assertThat(notification.extras.getString(NOTIFICATION_OVERRIDE_NAME_EXTRA))
+ .isEqualTo(STRING_NEARBY);
+ }
+}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationManagerTest.java
index 4fb6b37..9670a3f 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationManagerTest.java
@@ -18,38 +18,62 @@
import static org.mockito.Mockito.when;
+import android.app.NotificationManager;
import android.content.Context;
+import android.content.res.Resources;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.HalfSheetResources;
+import com.android.server.nearby.fastpair.cache.DiscoveryItem;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import service.proto.Cache;
+
public class FastPairNotificationManagerTest {
- @Mock private Context mContext;
- private static final boolean USE_LARGE_ICON = true;
+ @Mock
+ private Context mContext;
+ @Mock
+ NotificationManager mNotificationManager;
+ @Mock
+ Resources mResources;
+ @Mock
+ private LocatorContextWrapper mLocatorContextWrapper;
+ @Mock
+ private Locator mLocator;
+
private static final int NOTIFICATION_ID = 1;
- private static final String COMPANION_APP = "companionApp";
private static final int BATTERY_LEVEL = 1;
private static final String DEVICE_NAME = "deviceName";
- private static final String ADDRESS = "address";
private FastPairNotificationManager mFastPairNotificationManager;
- private LocatorContextWrapper mLocatorContextWrapper;
+ private DiscoveryItem mItem;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mLocatorContextWrapper = new LocatorContextWrapper(mContext);
when(mContext.getContentResolver()).thenReturn(
InstrumentationRegistry.getInstrumentation().getContext().getContentResolver());
+ when(mLocatorContextWrapper.getResources()).thenReturn(mResources);
+ when(mLocatorContextWrapper.getLocator()).thenReturn(mLocator);
+ HalfSheetResources.setResourcesContextForTest(mLocatorContextWrapper);
+ // Real context is needed
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ FastPairNotificationManager fastPairNotificationManager =
mFastPairNotificationManager =
- new FastPairNotificationManager(mLocatorContextWrapper, null,
- USE_LARGE_ICON, NOTIFICATION_ID);
+ new FastPairNotificationManager(context, NOTIFICATION_ID, mNotificationManager,
+ new HalfSheetResources(mLocatorContextWrapper));
+ mLocator.overrideBindingForTest(FastPairNotificationManager.class,
+ fastPairNotificationManager);
+
+ mItem = new DiscoveryItem(mLocatorContextWrapper,
+ Cache.StoredDiscoveryItem.newBuilder().setTitle("Device Name").build());
}
@Test
@@ -60,17 +84,18 @@
@Test
public void showConnectingNotification() {
- mFastPairNotificationManager.showConnectingNotification();
+ mFastPairNotificationManager.showConnectingNotification(mItem);
}
@Test
public void showPairingFailedNotification() {
- mFastPairNotificationManager.showPairingFailedNotification(new byte[]{1});
+ mFastPairNotificationManager
+ .showPairingFailedNotification(mItem, new byte[]{1});
}
@Test
public void showPairingSucceededNotification() {
- mFastPairNotificationManager.showPairingSucceededNotification(COMPANION_APP,
- BATTERY_LEVEL, DEVICE_NAME, ADDRESS);
+ mFastPairNotificationManager
+ .showPairingSucceededNotification(mItem, BATTERY_LEVEL, DEVICE_NAME);
}
}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationsTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationsTest.java
new file mode 100644
index 0000000..cfebbde
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/notification/FastPairNotificationsTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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 com.android.server.nearby.fastpair.notification;
+
+import static com.android.server.nearby.fastpair.notification.FastPairNotificationManager.DEVICES_WITHIN_REACH_CHANNEL_ID;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.nearby.halfsheet.R;
+import com.android.server.nearby.common.locator.Locator;
+import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.HalfSheetResources;
+import com.android.server.nearby.fastpair.cache.DiscoveryItem;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import service.proto.Cache;
+
+public class FastPairNotificationsTest {
+ private static final Cache.StoredDiscoveryItem SCAN_FAST_PAIR_ITEM =
+ Cache.StoredDiscoveryItem.newBuilder()
+ .setDeviceName("TestName")
+ .build();
+ private static final String STRING_DEVICE = "Devices";
+ private static final String STRING_NEARBY = "Nearby";
+ private static final String STRING_YOUR_DEVICE = "Your saved device is available";
+ private static final String STRING_CONNECTING = "Connecting";
+ private static final String STRING_DEVICE_READY = "Device connected";
+
+ private static final byte[] ACCOUNT_KEY = new byte[]{0x01, 0x02};
+ @Mock
+ LocatorContextWrapper mContextWrapper;
+ @Mock
+ Locator mLocator;
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private Drawable mDrawable;
+
+ private DiscoveryItem mItem;
+ private HalfSheetResources mHalfSheetResources;
+ private FastPairNotifications mFastPairNotifications;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mHalfSheetResources = new HalfSheetResources(mContext);
+ Context realContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mFastPairNotifications =
+ new FastPairNotifications(realContext, mHalfSheetResources);
+ HalfSheetResources.setResourcesContextForTest(mContext);
+
+ when(mContextWrapper.getLocator()).thenReturn(mLocator);
+ when(mContext.getResources()).thenReturn(mResources);
+
+ when(mResources.getString(eq(R.string.common_devices))).thenReturn(STRING_DEVICE);
+ when(mResources.getString(eq(R.string.common_nearby_title))).thenReturn(STRING_NEARBY);
+ when(mResources.getString(eq(R.string.fast_pair_your_device)))
+ .thenReturn(STRING_YOUR_DEVICE);
+ when(mResources.getString(eq(R.string.common_connecting))).thenReturn(STRING_CONNECTING);
+ when(mResources.getString(eq(R.string.fast_pair_device_ready)))
+ .thenReturn(STRING_DEVICE_READY);
+ when(mResources.getDrawable(eq(R.drawable.quantum_ic_devices_other_vd_theme_24), any()))
+ .thenReturn(mDrawable);
+
+ mItem = new DiscoveryItem(mContextWrapper, SCAN_FAST_PAIR_ITEM);
+ }
+
+ @Test
+ public void verify_progressNotification() {
+ Notification notification = mFastPairNotifications.progressNotification(mItem);
+
+ assertThat(notification.getChannelId()).isEqualTo(DEVICES_WITHIN_REACH_CHANNEL_ID);
+ assertThat(notification.getSmallIcon().getResId())
+ .isEqualTo(R.drawable.quantum_ic_devices_other_vd_theme_24);
+ assertThat(notification.category).isEqualTo(Notification.CATEGORY_PROGRESS);
+ assertThat(notification.tickerText.toString()).isEqualTo(STRING_CONNECTING);
+ }
+
+ @Test
+ public void verify_discoveryNotification() {
+ Notification notification =
+ mFastPairNotifications.discoveryNotification(mItem, ACCOUNT_KEY);
+
+ assertThat(notification.getChannelId()).isEqualTo(DEVICES_WITHIN_REACH_CHANNEL_ID);
+ assertThat(notification.getSmallIcon().getResId())
+ .isEqualTo(R.drawable.quantum_ic_devices_other_vd_theme_24);
+ assertThat(notification.category).isEqualTo(Notification.CATEGORY_RECOMMENDATION);
+ }
+
+ @Test
+ public void verify_succeededNotification() {
+ Notification notification = mFastPairNotifications
+ .pairingSucceededNotification(101, null, "model name", mItem);
+
+ assertThat(notification.getChannelId()).isEqualTo(DEVICES_WITHIN_REACH_CHANNEL_ID);
+ assertThat(notification.getSmallIcon().getResId())
+ .isEqualTo(R.drawable.quantum_ic_devices_other_vd_theme_24);
+ assertThat(notification.tickerText.toString()).isEqualTo(STRING_DEVICE_READY);
+ assertThat(notification.category).isEqualTo(Notification.CATEGORY_STATUS);
+ }
+
+ @Test
+ public void verify_failedNotification() {
+ Notification notification =
+ mFastPairNotifications.showPairingFailedNotification(mItem, ACCOUNT_KEY);
+
+ assertThat(notification.getChannelId()).isEqualTo(DEVICES_WITHIN_REACH_CHANNEL_ID);
+ assertThat(notification.getSmallIcon().getResId())
+ .isEqualTo(R.drawable.quantum_ic_devices_other_vd_theme_24);
+ assertThat(notification.category).isEqualTo(Notification.CATEGORY_ERROR);
+ }
+}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandlerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandlerTest.java
index bfe009c..2d496fd 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandlerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/HalfSheetPairingProgressHandlerTest.java
@@ -24,6 +24,7 @@
import android.bluetooth.BluetoothDevice;
import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection;
+import com.android.server.nearby.common.eventloop.EventLoop;
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
import com.android.server.nearby.fastpair.cache.DiscoveryItem;
@@ -57,6 +58,8 @@
FastPairConnection mFastPairConnection;
@Mock
FootprintsDeviceManager mFootprintsDeviceManager;
+ @Mock
+ EventLoop mEventLoop;
private static final String MAC_ADDRESS = "00:11:22:33:44:55";
private static final byte[] ACCOUNT_KEY = new byte[]{0x01, 0x02};
@@ -66,6 +69,7 @@
private static HalfSheetPairingProgressHandler sHalfSheetPairingProgressHandler;
private static DiscoveryItem sDiscoveryItem;
private static BluetoothDevice sBluetoothDevice;
+ private static FastPairHalfSheetManager sFastPairHalfSheetManager;
@Before
public void setup() {
@@ -73,10 +77,10 @@
when(mContextWrapper.getLocator()).thenReturn(mLocator);
mLocator.overrideBindingForTest(FastPairCacheManager.class, mFastPairCacheManager);
mLocator.overrideBindingForTest(Clock.class, mClock);
- FastPairHalfSheetManager mfastPairHalfSheetManager =
- new FastPairHalfSheetManager(mContextWrapper);
- mLocator.bind(FastPairHalfSheetManager.class, mfastPairHalfSheetManager);
- when(mLocator.get(FastPairHalfSheetManager.class)).thenReturn(mfastPairHalfSheetManager);
+ sFastPairHalfSheetManager = new FastPairHalfSheetManager(mContextWrapper);
+ mLocator.bind(FastPairHalfSheetManager.class, sFastPairHalfSheetManager);
+ when(mLocator.get(FastPairHalfSheetManager.class)).thenReturn(sFastPairHalfSheetManager);
+ when(mLocator.get(EventLoop.class)).thenReturn(mEventLoop);
sDiscoveryItem = FakeDiscoveryItems.newFastPairDiscoveryItem(mContextWrapper);
sDiscoveryItem.setStoredItemForTest(
sDiscoveryItem.getStoredItemForTest().toBuilder()
@@ -126,6 +130,7 @@
@Test
public void testonPairingStarted() {
sHalfSheetPairingProgressHandler.onPairingStarted();
+ assertThat(sFastPairHalfSheetManager.isActivePairing()).isTrue();
}
@Test
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandlerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandlerTest.java
index 24f296c..5c61ddb 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandlerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/NotificationPairingProgressHandlerTest.java
@@ -20,13 +20,18 @@
import static org.mockito.Mockito.when;
+import android.app.NotificationManager;
import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.res.Resources;
import androidx.annotation.Nullable;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection;
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.HalfSheetResources;
import com.android.server.nearby.fastpair.cache.DiscoveryItem;
import com.android.server.nearby.fastpair.cache.FastPairCacheManager;
import com.android.server.nearby.fastpair.footprint.FootprintsDeviceManager;
@@ -62,6 +67,10 @@
FootprintsDeviceManager mFootprintsDeviceManager;
@Mock
android.bluetooth.BluetoothManager mBluetoothManager;
+ @Mock
+ NotificationManager mNotificationManager;
+ @Mock
+ Resources mResources;
private static final String MAC_ADDRESS = "00:11:22:33:44:55";
private static final byte[] ACCOUNT_KEY = new byte[]{0x01, 0x02};
@@ -76,6 +85,9 @@
when(mContextWrapper.getSystemService(BluetoothManager.class))
.thenReturn(mBluetoothManager);
when(mContextWrapper.getLocator()).thenReturn(mLocator);
+ when(mContextWrapper.getResources()).thenReturn(mResources);
+ HalfSheetResources.setResourcesContextForTest(mContextWrapper);
+
mLocator.overrideBindingForTest(FastPairCacheManager.class,
mFastPairCacheManager);
mLocator.overrideBindingForTest(Clock.class, mClock);
@@ -126,11 +138,17 @@
private NotificationPairingProgressHandler createProgressHandler(
@Nullable byte[] accountKey, DiscoveryItem fastPairItem) {
- FastPairNotificationManager fastPairNotificationManager =
- new FastPairNotificationManager(mContextWrapper, fastPairItem, true);
FastPairHalfSheetManager fastPairHalfSheetManager =
new FastPairHalfSheetManager(mContextWrapper);
+ // Real context is needed
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ FastPairNotificationManager fastPairNotificationManager =
+ new FastPairNotificationManager(context, 1234, mNotificationManager,
+ new HalfSheetResources(mContextWrapper));
mLocator.overrideBindingForTest(FastPairHalfSheetManager.class, fastPairHalfSheetManager);
+ mLocator.overrideBindingForTest(FastPairNotificationManager.class,
+ fastPairNotificationManager);
+
NotificationPairingProgressHandler mNotificationPairingProgressHandler =
new NotificationPairingProgressHandler(
mContextWrapper,
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBaseTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBaseTest.java
index a3eb50c..6d769df 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBaseTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/pairinghandler/PairingProgressHandlerBaseTest.java
@@ -20,16 +20,21 @@
import static org.mockito.Mockito.when;
+import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.res.Resources;
import androidx.annotation.Nullable;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection;
import com.android.server.nearby.common.bluetooth.fastpair.Preferences;
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.HalfSheetResources;
import com.android.server.nearby.fastpair.cache.DiscoveryItem;
import com.android.server.nearby.fastpair.cache.FastPairCacheManager;
import com.android.server.nearby.fastpair.footprint.FootprintsDeviceManager;
@@ -64,6 +69,10 @@
FastPairConnection mFastPairConnection;
@Mock
BluetoothManager mBluetoothManager;
+ @Mock
+ Resources mResources;
+ @Mock
+ NotificationManager mNotificationManager;
private static final String MAC_ADDRESS = "00:11:22:33:44:55";
private static final byte[] ACCOUNT_KEY = new byte[]{0x01, 0x02};
@@ -81,6 +90,9 @@
mLocator.overrideBindingForTest(FastPairCacheManager.class,
mFastPairCacheManager);
mLocator.overrideBindingForTest(Clock.class, mClock);
+ when(mContextWrapper.getResources()).thenReturn(mResources);
+ HalfSheetResources.setResourcesContextForTest(mContextWrapper);
+
sBluetoothDevice =
BluetoothAdapter.getDefaultAdapter().getRemoteDevice("00:11:22:33:44:55");
sDiscoveryItem = FakeDiscoveryItems.newFastPairDiscoveryItem(mContextWrapper);
@@ -205,10 +217,17 @@
private PairingProgressHandlerBase createProgressHandler(
@Nullable byte[] accountKey, DiscoveryItem fastPairItem, boolean isRetroactivePair) {
- FastPairNotificationManager fastPairNotificationManager =
- new FastPairNotificationManager(mContextWrapper, fastPairItem, true);
+
FastPairHalfSheetManager fastPairHalfSheetManager =
new FastPairHalfSheetManager(mContextWrapper);
+ // Real context is needed
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ FastPairNotificationManager fastPairNotificationManager =
+ new FastPairNotificationManager(context, 1234, mNotificationManager,
+ new HalfSheetResources(mContextWrapper));
+
+ mLocator.overrideBindingForTest(FastPairNotificationManager.class,
+ fastPairNotificationManager);
mLocator.overrideBindingForTest(FastPairHalfSheetManager.class, fastPairHalfSheetManager);
PairingProgressHandlerBase pairingProgressHandlerBase =
PairingProgressHandlerBase.create(
diff --git a/nearby/tests/unit/src/com/android/server/nearby/util/ArrayUtilsTest.java b/nearby/tests/unit/src/com/android/server/nearby/util/ArrayUtilsTest.java
index 0fe28df..a759baf 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/util/ArrayUtilsTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/util/ArrayUtilsTest.java
@@ -59,4 +59,22 @@
assertThat(ArrayUtils.concatByteArrays(BYTES_ONE, BYTES_EMPTY, BYTES_TWO))
.isEqualTo(BYTES_ALL);
}
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIsEmptyNull_returnsTrue() {
+ assertThat(ArrayUtils.isEmpty(null)).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIsEmpty_returnsTrue() {
+ assertThat(ArrayUtils.isEmpty(new byte[]{})).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIsEmpty_returnsFalse() {
+ assertThat(ArrayUtils.isEmpty(BYTES_ALL)).isFalse();
+ }
}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/util/DataUtilsTest.java b/nearby/tests/unit/src/com/android/server/nearby/util/DataUtilsTest.java
index a742b3d..ac90b9f 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/util/DataUtilsTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/util/DataUtilsTest.java
@@ -30,6 +30,7 @@
public final class DataUtilsTest {
private static final String BLUETOOTH_ADDRESS = "00:11:22:33:FF:EE";
+ private static final String MODEL_ID = "model_id";
private static final String APP_PACKAGE = "test_package";
private static final String APP_ACTION_URL =
"intent:#Intent;action=cto_be_set%3AACTION_MAGIC_PAIR;"
@@ -61,7 +62,7 @@
@Test
public void test_toScanFastPairStoreItem_withAccount() {
Cache.ScanFastPairStoreItem item = DataUtils.toScanFastPairStoreItem(
- createObservedDeviceResponse(), BLUETOOTH_ADDRESS, ACCOUNT);
+ createObservedDeviceResponse(), BLUETOOTH_ADDRESS, MODEL_ID, ACCOUNT);
assertThat(item.getAddress()).isEqualTo(BLUETOOTH_ADDRESS);
assertThat(item.getActionUrl()).isEqualTo(APP_ACTION_URL);
assertThat(item.getDeviceName()).isEqualTo(DEVICE_NAME);
@@ -93,7 +94,7 @@
@Test
public void test_toScanFastPairStoreItem_withoutAccount() {
Cache.ScanFastPairStoreItem item = DataUtils.toScanFastPairStoreItem(
- createObservedDeviceResponse(), BLUETOOTH_ADDRESS, /* account= */ null);
+ createObservedDeviceResponse(), BLUETOOTH_ADDRESS, MODEL_ID, /* account= */ null);
FastPairStrings strings = item.getFastPairStrings();
assertThat(strings.getInitialPairingDescription())
.isEqualTo(MESSAGE_INIT_NOTIFY_DESCRIPTION_NO_ACCOUNT);
@@ -102,7 +103,7 @@
@Test
public void test_toString() {
Cache.ScanFastPairStoreItem item = DataUtils.toScanFastPairStoreItem(
- createObservedDeviceResponse(), BLUETOOTH_ADDRESS, ACCOUNT);
+ createObservedDeviceResponse(), BLUETOOTH_ADDRESS, MODEL_ID, ACCOUNT);
assertThat(DataUtils.toString(item))
.isEqualTo("ScanFastPairStoreItem=[address:00:11:22:33:FF:EE, "
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index f24e55f..891c2dd 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-next_app_data = []
+next_app_data = [ ":CtsHostsideNetworkTestsAppNext" ]
// The above line is put in place to prevent any future automerger merge conflict between aosp,
// downstream branches. The CtsHostsideNetworkTestsAppNext target will not exist in
diff --git a/tests/cts/hostside/app2/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml
index ff7240d..2c2d957 100644
--- a/tests/cts/hostside/app2/AndroidManifest.xml
+++ b/tests/cts/hostside/app2/AndroidManifest.xml
@@ -20,6 +20,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
@@ -45,7 +46,11 @@
<service android:name=".MyService"
android:exported="true"/>
<service android:name=".MyForegroundService"
- android:exported="true"/>
+ android:foregroundServiceType="specialUse"
+ android:exported="true">
+ <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
+ android:value="Connectivity" />
+ </service>
<service android:name=".RemoteSocketFactoryService"
android:exported="true"/>