AdvertiseManager.java revision 18999c2cfd477050de0ca88c3a73458235d82656
127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang/* 227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Copyright (C) 2014 The Android Open Source Project 327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Licensed under the Apache License, Version 2.0 (the "License"); 527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * you may not use this file except in compliance with the License. 627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * You may obtain a copy of the License at 727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * http://www.apache.org/licenses/LICENSE-2.0 927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 1027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Unless required by applicable law or agreed to in writing, software 1127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * distributed under the License is distributed on an "AS IS" BASIS, 1227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * See the License for the specific language governing permissions and 1427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * limitations under the License. 1527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 1627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 1727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangpackage com.android.bluetooth.gatt; 1827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 19bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wangimport android.bluetooth.BluetoothUuid; 2027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.bluetooth.le.AdvertiseCallback; 2127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.bluetooth.le.AdvertiseData; 2227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.bluetooth.le.AdvertiseSettings; 2327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.os.Handler; 2427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.os.HandlerThread; 2527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.os.Looper; 2627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.os.Message; 2727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.os.ParcelUuid; 2827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.os.RemoteException; 2927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.util.Log; 3027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 3127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport com.android.bluetooth.Utils; 3227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport com.android.bluetooth.btservice.AdapterService; 3327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 3427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.nio.ByteBuffer; 3527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.nio.ByteOrder; 3627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.HashSet; 3727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.List; 3827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.Set; 3927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.UUID; 4027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.concurrent.CountDownLatch; 4127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.concurrent.TimeUnit; 4227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 4327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang/** 4427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Manages Bluetooth LE advertising operations and interacts with bluedroid stack. 4527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 4627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @hide 4727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 4827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangclass AdvertiseManager { 4927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final boolean DBG = GattServiceConfig.DBG; 5027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final String TAG = GattServiceConfig.TAG_PREFIX + "AdvertiseManager"; 5127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 5227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Timeout for each controller operation. 5327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int OPERATION_TIME_OUT_MILLIS = 500; 5427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 5527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Message for advertising operations. 5627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int MSG_START_ADVERTISING = 0; 5727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int MSG_STOP_ADVERTISING = 1; 5827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 5927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private final GattService mService; 6027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private final Set<AdvertiseClient> mAdvertiseClients; 6127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private final AdvertiseNative mAdvertiseNative; 6227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 6327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Handles advertise operations. 6427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private ClientHandler mHandler; 6527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 6627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // CountDownLatch for blocking advertise operations. 6727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private CountDownLatch mLatch; 6827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 6927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 7027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Constructor of {@link AdvertiseManager}. 7127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 7227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseManager(GattService service) { 7327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mService = service; 7427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("advertise manager created"); 7527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseClients = new HashSet<AdvertiseClient>(); 7627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseNative = new AdvertiseNative(); 7727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 7827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 7927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 8027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Start a {@link HandlerThread} that handles advertising operations. 8127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 8227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void start() { 8327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang HandlerThread thread = new HandlerThread("BluetoothAdvertiseManager"); 8427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang thread.start(); 8527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mHandler = new ClientHandler(thread.getLooper()); 8627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 8727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 8827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void cleanup() { 8927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("advertise clients cleared"); 9027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseClients.clear(); 9127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 9227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 9327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 9427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Start BLE advertising. 9527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 9627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param client Advertise client. 9727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 9827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void startAdvertising(AdvertiseClient client) { 9927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client == null) { 10027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 10127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 10227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Message message = new Message(); 10327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.what = MSG_START_ADVERTISING; 10427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.obj = client; 10527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mHandler.sendMessage(message); 10627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 10727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 10827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 10927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Stop BLE advertising. 11027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 11127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void stopAdvertising(AdvertiseClient client) { 11227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client == null) { 11327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 11427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 11527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Message message = new Message(); 11627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.what = MSG_STOP_ADVERTISING; 11727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.obj = client; 11827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mHandler.sendMessage(message); 11927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 12027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 12127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 12227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Signals the callback is received. 12327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 12427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param clientIf Identifier for the client. 12527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param status Status of the callback. 12627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 12727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void callbackDone(int clientIf, int status) { 12827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (status == AdvertiseCallback.ADVERTISE_SUCCESS) { 12927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mLatch.countDown(); 13027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } else { 13127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note in failure case we'll wait for the latch to timeout(which takes 100ms) and 13227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // the mClientHandler thread will be blocked till timeout. 13327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 13427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 13527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 13627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 13727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Post callback status to app process. 13827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void postCallback(int clientIf, int status) { 13927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang try { 14018999c2cfd477050de0ca88c3a73458235d82656Wei Wang AdvertiseClient client = getAdvertiseClient(clientIf); 14118999c2cfd477050de0ca88c3a73458235d82656Wei Wang AdvertiseSettings settings = (client == null) ? null : client.settings; 14218999c2cfd477050de0ca88c3a73458235d82656Wei Wang boolean isStart = true; 14318999c2cfd477050de0ca88c3a73458235d82656Wei Wang mService.onMultipleAdvertiseCallback(clientIf, status, isStart, settings); 14427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } catch (RemoteException e) { 14527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang loge("failed onMultipleAdvertiseCallback", e); 14627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 14727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 14827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 14918999c2cfd477050de0ca88c3a73458235d82656Wei Wang private AdvertiseClient getAdvertiseClient(int clientIf) { 15018999c2cfd477050de0ca88c3a73458235d82656Wei Wang for (AdvertiseClient client : mAdvertiseClients) { 15118999c2cfd477050de0ca88c3a73458235d82656Wei Wang if (client.clientIf == clientIf) { 15218999c2cfd477050de0ca88c3a73458235d82656Wei Wang return client; 15318999c2cfd477050de0ca88c3a73458235d82656Wei Wang } 15418999c2cfd477050de0ca88c3a73458235d82656Wei Wang } 15518999c2cfd477050de0ca88c3a73458235d82656Wei Wang return null; 15618999c2cfd477050de0ca88c3a73458235d82656Wei Wang } 15718999c2cfd477050de0ca88c3a73458235d82656Wei Wang 15827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Handler class that handles BLE advertising operations. 15927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private class ClientHandler extends Handler { 16027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 16127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ClientHandler(Looper looper) { 16227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang super(looper); 16327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 16427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 16527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang @Override 16627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang public void handleMessage(Message msg) { 16727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("message : " + msg.what); 16827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseClient client = (AdvertiseClient) msg.obj; 16927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang switch (msg.what) { 17027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case MSG_START_ADVERTISING: 17127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang handleStartAdvertising(client); 17227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang break; 17327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case MSG_STOP_ADVERTISING: 17427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang handleStopAdvertising(client); 17527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang break; 17627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 17727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Shouldn't happen. 17827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.e(TAG, "recieve an unknown message : " + msg.what); 17927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang break; 18027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 18127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 18227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 18327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void handleStartAdvertising(AdvertiseClient client) { 18427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Utils.enforceAdminPermission(mService); 18527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int clientIf = client.clientIf; 18627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (mAdvertiseClients.contains(clientIf)) { 18727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); 18827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 18927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 19027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 19127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (mAdvertiseClients.size() >= maxAdvertiseInstances()) { 19227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, 19327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS); 19427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 19527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 19627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!mAdvertiseNative.startAdverising(client)) { 19727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 19827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 19927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 20027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseClients.add(client); 20127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_SUCCESS); 20227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 20327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 20427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Handles stop advertising. 20527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void handleStopAdvertising(AdvertiseClient client) { 20627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Utils.enforceAdminPermission(mService); 20727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client == null) { 20827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 20927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 21027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int clientIf = client.clientIf; 21127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("advertise clients size " + mAdvertiseClients.size()); 21227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (mAdvertiseClients.contains(client)) { 21327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseNative.stopAdvertising(client); 21461b76fd94c45ee1909cde1d08a643fc031ef287fYicheng Fan mAdvertiseClients.remove(client); 21527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 21627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 21727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 21827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Returns maximum advertise instances supported by controller. 21927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private int maxAdvertiseInstances() { 22027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdapterService adapter = AdapterService.getAdapterService(); 22127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int numOfAdvtInstances = adapter.getNumOfAdvertisementInstancesSupported(); 22227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note numOfAdvtInstances includes the standard advertising instance. 22327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // TODO: remove - 1 once the stack is able to include standard instance for multiple 22427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // advertising. 22527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return numOfAdvtInstances - 1; 22627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 22727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 22827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 22927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Class that wraps advertise native related constants, methods etc. 23027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private class AdvertiseNative { 23127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Advertise interval for different modes. 23227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_HIGH_MILLS = 1000; 23327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_MEDIUM_MILLS = 250; 23427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_LOW_MILLS = 100; 23527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 23627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Add some randomness to the advertising min/max interval so the controller can do some 23727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // optimization. 23827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_DELTA_UNIT = 10; 23927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_MICROS_PER_UNIT = 625; 24027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 24127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // The following constants should be kept the same as those defined in bt stack. 24227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_37 = 1 << 0; 24327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_38 = 1 << 1; 24427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_39 = 1 << 2; 24527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_ALL = 24627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ADVERTISING_CHANNEL_37 | ADVERTISING_CHANNEL_38 | ADVERTISING_CHANNEL_39; 24727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 24827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_MIN = 0; 24927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_LOW = 1; 25027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_MID = 2; 25127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_UPPER = 3; 25227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note this is not exposed to the Java API. 25327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_MAX = 4; 25427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 25527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note we don't expose connectable directed advertising to API. 25627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_EVENT_TYPE_CONNECTABLE = 0; 25727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_EVENT_TYPE_SCANNABLE = 2; 25827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_EVENT_TYPE_NON_CONNECTABLE = 3; 25927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 26027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang boolean startAdverising(AdvertiseClient client) { 26127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int clientIf = client.clientIf; 26227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang resetCountDownLatch(); 26327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseNative.enableAdvertising(client); 26427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!waitForCallback()) { 26527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 26627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 26727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang resetCountDownLatch(); 26827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseNative.setAdvertisingData(clientIf, client.advertiseData, false); 26927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!waitForCallback()) { 27027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 27127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 27227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client.scanResponse != null) { 27327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang resetCountDownLatch(); 27427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseNative.setAdvertisingData(clientIf, client.scanResponse, true); 27527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!waitForCallback()) { 27627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 27727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 27827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 27927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return true; 28027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 28127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 28227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void stopAdvertising(AdvertiseClient client) { 28327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang gattClientDisableAdvNative(client.clientIf); 28427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 28527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 28627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void resetCountDownLatch() { 28727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mLatch = new CountDownLatch(1); 28827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 28927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 29027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Returns true if mLatch reaches 0, false if timeout or interrupted. 29127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private boolean waitForCallback() { 29227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang try { 29327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return mLatch.await(OPERATION_TIME_OUT_MILLIS, TimeUnit.MILLISECONDS); 29427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } catch (InterruptedException e) { 29527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 29627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 29727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 29827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 29927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void enableAdvertising(AdvertiseClient client) { 30027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int clientIf = client.clientIf; 30127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int minAdvertiseUnit = (int) getAdvertisingIntervalUnit(client.settings); 30227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int maxAdvertiseUnit = minAdvertiseUnit + ADVERTISING_INTERVAL_DELTA_UNIT; 30327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int advertiseEventType = getAdvertisingEventType(client); 30427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int txPowerLevel = getTxPowerLevel(client.settings); 30527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang gattClientEnableAdvNative( 30627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang clientIf, 30727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang minAdvertiseUnit, maxAdvertiseUnit, 30827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang advertiseEventType, 30927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ADVERTISING_CHANNEL_ALL, 31027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang txPowerLevel); 31127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 31227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 31327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void setAdvertisingData(int clientIf, AdvertiseData data, boolean isScanResponse) { 31427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (data == null) { 31527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 31627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 31786c292ab0f0fed25345a2eaef0fd92ff9c72a9e5Wei Wang boolean includeName = data.getIncludeDeviceName(); 31827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang boolean includeTxPower = data.getIncludeTxPowerLevel(); 31927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int appearance = 0; 320bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] manufacturerData = getManufacturerData(data); 32127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 322bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] serviceData = getServiceData(data); 32327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang byte[] serviceUuids; 32427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (data.getServiceUuids() == null) { 32527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang serviceUuids = new byte[0]; 32627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } else { 32727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ByteBuffer advertisingUuidBytes = ByteBuffer.allocate( 32827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang data.getServiceUuids().size() * 16) 32927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang .order(ByteOrder.LITTLE_ENDIAN); 33027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang for (ParcelUuid parcelUuid : data.getServiceUuids()) { 33127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang UUID uuid = parcelUuid.getUuid(); 332bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Least significant bits first as the advertising UUID should be in 33327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // little-endian. 33427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang advertisingUuidBytes.putLong(uuid.getLeastSignificantBits()) 33527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang .putLong(uuid.getMostSignificantBits()); 33627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 33727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang serviceUuids = advertisingUuidBytes.array(); 33827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 33927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang gattClientSetAdvDataNative(clientIf, isScanResponse, includeName, includeTxPower, 34027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang appearance, 34127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang manufacturerData, serviceData, serviceUuids); 34227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 34327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 344bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Combine manufacturer id and manufacturer data. 345bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang private byte[] getManufacturerData(AdvertiseData advertiseData) { 346e34b91565499994a4b04a1014432c8f90678972aWei Wang if (advertiseData.getManufacturerSpecificData().size() == 0) { 347bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return new byte[0]; 348bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 349e34b91565499994a4b04a1014432c8f90678972aWei Wang int manufacturerId = advertiseData.getManufacturerSpecificData().keyAt(0); 350e34b91565499994a4b04a1014432c8f90678972aWei Wang byte[] manufacturerData = advertiseData.getManufacturerSpecificData().get( 351e34b91565499994a4b04a1014432c8f90678972aWei Wang manufacturerId); 352bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang int dataLen = 2 + (manufacturerData == null ? 0 : manufacturerData.length); 353bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] concated = new byte[dataLen]; 354bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // / First two bytes are manufacturer id in little-endian. 355bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[0] = (byte) (manufacturerId & 0xFF); 356bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[1] = (byte) ((manufacturerId >> 8) & 0xFF); 357bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang if (manufacturerData != null) { 358bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang System.arraycopy(manufacturerData, 0, concated, 2, manufacturerData.length); 359bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 360bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return concated; 361bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 362bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang 363bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Combine service UUID and service data. 364bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang private byte[] getServiceData(AdvertiseData advertiseData) { 365e34b91565499994a4b04a1014432c8f90678972aWei Wang if (advertiseData.getServiceData().isEmpty()) { 366bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return new byte[0]; 367bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 368e34b91565499994a4b04a1014432c8f90678972aWei Wang ParcelUuid uuid = advertiseData.getServiceData().keySet().iterator().next(); 369e34b91565499994a4b04a1014432c8f90678972aWei Wang byte[] serviceData = advertiseData.getServiceData().get(uuid); 370bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang int dataLen = 2 + (serviceData == null ? 0 : serviceData.length); 371bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] concated = new byte[dataLen]; 372bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Extract 16 bit UUID value. 373bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang int uuidValue = BluetoothUuid.getServiceIdentifierFromParcelUuid( 374e34b91565499994a4b04a1014432c8f90678972aWei Wang uuid); 375bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // First two bytes are service data UUID in little-endian. 376bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[0] = (byte) (uuidValue & 0xFF); 377bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[1] = (byte) ((uuidValue >> 8) & 0xFF); 378bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang if (serviceData != null) { 379bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang System.arraycopy(serviceData, 0, concated, 2, serviceData.length); 380bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 381bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return concated; 382bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 383bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang 38427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Convert settings tx power level to stack tx power level. 38527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private int getTxPowerLevel(AdvertiseSettings settings) { 38627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang switch (settings.getTxPowerLevel()) { 38727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW: 38827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_MIN; 38927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_LOW: 39027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_LOW; 39127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM: 39227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_MID; 39327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_HIGH: 39427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_UPPER; 39527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 39627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Shouldn't happen, just in case. 39727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_MID; 39827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 39927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 40027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 40127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Convert advertising event type to stack values. 40227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private int getAdvertisingEventType(AdvertiseClient client) { 40327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseSettings settings = client.settings; 40427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (settings.getIsConnectable()) { 40527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_EVENT_TYPE_CONNECTABLE; 40627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 40727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return client.scanResponse == null ? ADVERTISING_EVENT_TYPE_NON_CONNECTABLE 40827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang : ADVERTISING_EVENT_TYPE_SCANNABLE; 40927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 41027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 41127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Convert advertising milliseconds to advertising units(one unit is 0.625 millisecond). 41227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private long getAdvertisingIntervalUnit(AdvertiseSettings settings) { 41327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang switch (settings.getMode()) { 41427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_MODE_LOW_POWER: 41527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return millsToUnit(ADVERTISING_INTERVAL_HIGH_MILLS); 41627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_MODE_BALANCED: 41727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return millsToUnit(ADVERTISING_INTERVAL_MEDIUM_MILLS); 41827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY: 41927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return millsToUnit(ADVERTISING_INTERVAL_LOW_MILLS); 42027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 42127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Shouldn't happen, just in case. 42227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return millsToUnit(ADVERTISING_INTERVAL_HIGH_MILLS); 42327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 42427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 42527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 42627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private long millsToUnit(int millisecond) { 42727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return TimeUnit.MILLISECONDS.toMicros(millisecond) 42827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang / ADVERTISING_INTERVAL_MICROS_PER_UNIT; 42927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 43027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 43127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Native functions 43227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientDisableAdvNative(int client_if); 43327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 43427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientEnableAdvNative(int client_if, 43527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int min_interval, int max_interval, int adv_type, int chnl_map, 43627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int tx_power); 43727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 43827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientUpdateAdvNative(int client_if, 43927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int min_interval, int max_interval, int adv_type, int chnl_map, 44027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int tx_power); 44127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 44227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientSetAdvDataNative(int client_if, 44327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang boolean set_scan_rsp, boolean incl_name, boolean incl_txpower, int appearance, 44427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang byte[] manufacturer_data, byte[] service_data, byte[] service_uuid); 44527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 44627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 44727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void logd(String s) { 44827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (DBG) { 44927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.d(TAG, s); 45027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 45127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 45227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 45327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void loge(String s, Exception e) { 45427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.e(TAG, s, e); 45527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 45627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 45727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang} 458