diff options
author | frankfeng <frankfeng@google.com> | 2021-12-23 22:16:17 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-12-23 22:16:17 +0000 |
commit | 233a9846391b42adcaa36eea9f39980dedb43be2 (patch) | |
tree | 71f65f7f55b0604e60173d7004994baa85e97c35 /src/main/java/com/google/android/mobly/snippet/bundled/BluetoothLeAdvertiserSnippet.java | |
parent | bcbece2f1ebff711bbb8358a4dc709420d93e3a1 (diff) | |
parent | b3028abea8c6094b70814268affd960294cb72a6 (diff) | |
download | mobly-bundled-snippets-233a9846391b42adcaa36eea9f39980dedb43be2.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into mymerge am: b3028abea8
Original change: https://android-review.googlesource.com/c/platform/external/mobly-bundled-snippets/+/1932819
Change-Id: I1c95dee299fd6b1ebd2a4dd7e83252e5b0275bf7
Diffstat (limited to 'src/main/java/com/google/android/mobly/snippet/bundled/BluetoothLeAdvertiserSnippet.java')
-rw-r--r-- | src/main/java/com/google/android/mobly/snippet/bundled/BluetoothLeAdvertiserSnippet.java | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/BluetoothLeAdvertiserSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/BluetoothLeAdvertiserSnippet.java new file mode 100644 index 0000000..e161a5b --- /dev/null +++ b/src/main/java/com/google/android/mobly/snippet/bundled/BluetoothLeAdvertiserSnippet.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2017 Google Inc. + * + * 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.google.android.mobly.snippet.bundled; + +import android.annotation.TargetApi; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.le.AdvertiseCallback; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.os.Build; +import android.os.Bundle; +import android.os.ParcelUuid; +import com.google.android.mobly.snippet.Snippet; +import com.google.android.mobly.snippet.bundled.utils.JsonDeserializer; +import com.google.android.mobly.snippet.bundled.utils.JsonSerializer; +import com.google.android.mobly.snippet.bundled.utils.RpcEnum; +import com.google.android.mobly.snippet.event.EventCache; +import com.google.android.mobly.snippet.event.SnippetEvent; +import com.google.android.mobly.snippet.rpc.AsyncRpc; +import com.google.android.mobly.snippet.rpc.Rpc; +import com.google.android.mobly.snippet.rpc.RpcMinSdk; +import com.google.android.mobly.snippet.util.Log; +import java.util.HashMap; +import org.json.JSONException; +import org.json.JSONObject; + +/** Snippet class exposing Android APIs in WifiManager. */ +@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) +public class BluetoothLeAdvertiserSnippet implements Snippet { + private static class BluetoothLeAdvertiserSnippetException extends Exception { + private static final long serialVersionUID = 1; + + public BluetoothLeAdvertiserSnippetException(String msg) { + super(msg); + } + } + + private final BluetoothLeAdvertiser mAdvertiser; + private static final EventCache sEventCache = EventCache.getInstance(); + + private final HashMap<String, AdvertiseCallback> mAdvertiseCallbacks = new HashMap<>(); + + public BluetoothLeAdvertiserSnippet() { + mAdvertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser(); + } + + /** + * Start Bluetooth LE advertising. + * + * <p>This can be called multiple times, and each call is associated with a {@link + * AdvertiseCallback} object, which is used to stop the advertising. + * + * @param callbackId + * @param advertiseSettings A JSONObject representing a {@link AdvertiseSettings object}. E.g. + * <pre> + * { + * "AdvertiseMode": "ADVERTISE_MODE_BALANCED", + * "Timeout": (int, milliseconds), + * "Connectable": (bool), + * "TxPowerLevel": "ADVERTISE_TX_POWER_LOW" + * } + * </pre> + * + * @param advertiseData A JSONObject representing a {@link AdvertiseData} object. E.g. + * <pre> + * { + * "IncludeDeviceName": (bool), + * # JSON list, each element representing a set of service data, which is composed of + * # a UUID, and an optional string. + * "ServiceData": [ + * { + * "UUID": (A string representation of {@link ParcelUuid}), + * "Data": (Optional, The string representation of what you want to + * advertise, base64 encoded) + * # If you want to add a UUID without data, simply omit the "Data" + * # field. + * } + * ] + * } + * </pre> + * + * @throws BluetoothLeAdvertiserSnippetException + * @throws JSONException + */ + @RpcMinSdk(Build.VERSION_CODES.LOLLIPOP_MR1) + @AsyncRpc(description = "Start BLE advertising.") + public void bleStartAdvertising( + String callbackId, JSONObject advertiseSettings, JSONObject advertiseData) + throws BluetoothLeAdvertiserSnippetException, JSONException { + if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) { + throw new BluetoothLeAdvertiserSnippetException( + "Bluetooth is disabled, cannot start BLE advertising."); + } + AdvertiseSettings settings = JsonDeserializer.jsonToBleAdvertiseSettings(advertiseSettings); + AdvertiseData data = JsonDeserializer.jsonToBleAdvertiseData(advertiseData); + AdvertiseCallback advertiseCallback = new DefaultAdvertiseCallback(callbackId); + mAdvertiser.startAdvertising(settings, data, advertiseCallback); + mAdvertiseCallbacks.put(callbackId, advertiseCallback); + } + + /** + * Stop a BLE advertising. + * + * @param callbackId The callbackId corresponding to the {@link + * BluetoothLeAdvertiserSnippet#bleStartAdvertising} call that started the advertising. + * @throws BluetoothLeScannerSnippet.BluetoothLeScanSnippetException + */ + @RpcMinSdk(Build.VERSION_CODES.LOLLIPOP_MR1) + @Rpc(description = "Stop BLE advertising.") + public void bleStopAdvertising(String callbackId) throws BluetoothLeAdvertiserSnippetException { + AdvertiseCallback callback = mAdvertiseCallbacks.remove(callbackId); + if (callback == null) { + throw new BluetoothLeAdvertiserSnippetException( + "No advertising session found for ID " + callbackId); + } + mAdvertiser.stopAdvertising(callback); + } + + private static class DefaultAdvertiseCallback extends AdvertiseCallback { + private final String mCallbackId; + public static RpcEnum ADVERTISE_FAILURE_ERROR_CODE = + new RpcEnum.Builder() + .add("ADVERTISE_FAILED_ALREADY_STARTED", ADVERTISE_FAILED_ALREADY_STARTED) + .add("ADVERTISE_FAILED_DATA_TOO_LARGE", ADVERTISE_FAILED_DATA_TOO_LARGE) + .add( + "ADVERTISE_FAILED_FEATURE_UNSUPPORTED", + ADVERTISE_FAILED_FEATURE_UNSUPPORTED) + .add("ADVERTISE_FAILED_INTERNAL_ERROR", ADVERTISE_FAILED_INTERNAL_ERROR) + .add( + "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS", + ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) + .build(); + + public DefaultAdvertiseCallback(String callbackId) { + mCallbackId = callbackId; + } + + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + Log.e("Bluetooth LE advertising started with settings: " + settingsInEffect.toString()); + SnippetEvent event = new SnippetEvent(mCallbackId, "onStartSuccess"); + Bundle advertiseSettings = + JsonSerializer.serializeBleAdvertisingSettings(settingsInEffect); + event.getData().putBundle("SettingsInEffect", advertiseSettings); + sEventCache.postEvent(event); + } + + public void onStartFailure(int errorCode) { + Log.e("Bluetooth LE advertising failed to start with error code: " + errorCode); + SnippetEvent event = new SnippetEvent(mCallbackId, "onStartFailure"); + final String errorCodeString = ADVERTISE_FAILURE_ERROR_CODE.getString(errorCode); + event.getData().putString("ErrorCode", errorCodeString); + sEventCache.postEvent(event); + } + } + + @Override + public void shutdown() { + for (AdvertiseCallback callback : mAdvertiseCallbacks.values()) { + mAdvertiser.stopAdvertising(callback); + } + mAdvertiseCallbacks.clear(); + } +} |