AdvertiseManager.java revision ba73d4b554ff0016d6b11a6102c2a75b5b0c149d
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.Set; 3827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.UUID; 3927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.concurrent.CountDownLatch; 4027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport java.util.concurrent.TimeUnit; 4127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 4227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang/** 43a1664d61821a59145f8095a75373403a0c54244eWei Wang * Manages Bluetooth LE advertising operations and interacts with bluedroid stack. TODO: add tests. 4427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 4527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @hide 4627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 4727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangclass AdvertiseManager { 4827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final boolean DBG = GattServiceConfig.DBG; 4927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final String TAG = GattServiceConfig.TAG_PREFIX + "AdvertiseManager"; 5027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 5127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Timeout for each controller operation. 5227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int OPERATION_TIME_OUT_MILLIS = 500; 5327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 5427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Message for advertising operations. 5527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int MSG_START_ADVERTISING = 0; 5627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int MSG_STOP_ADVERTISING = 1; 5727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 5827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private final GattService mService; 59a1664d61821a59145f8095a75373403a0c54244eWei Wang private final AdapterService mAdapterService; 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 */ 72a1664d61821a59145f8095a75373403a0c54244eWei Wang AdvertiseManager(GattService service, AdapterService adapterService) { 7327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("advertise manager created"); 74a1664d61821a59145f8095a75373403a0c54244eWei Wang mService = service; 75a1664d61821a59145f8095a75373403a0c54244eWei Wang mAdapterService = adapterService; 7627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseClients = new HashSet<AdvertiseClient>(); 7727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseNative = new AdvertiseNative(); 7827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 7927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 8027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 8127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Start a {@link HandlerThread} that handles advertising operations. 8227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 8327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void start() { 8427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang HandlerThread thread = new HandlerThread("BluetoothAdvertiseManager"); 8527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang thread.start(); 8627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mHandler = new ClientHandler(thread.getLooper()); 8727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 8827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 8927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void cleanup() { 9027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("advertise clients cleared"); 9127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseClients.clear(); 92ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra 93ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra if (mHandler != null) { 94ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra // Shut down the thread 95ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra mHandler.removeCallbacksAndMessages(null); 96ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra Looper looper = mHandler.getLooper(); 97ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra if (looper != null) { 98ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra looper.quit(); 99ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra } 100ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra mHandler = null; 101ba73d4b554ff0016d6b11a6102c2a75b5b0c149dMatadeen Mishra } 10227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 10327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 10427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 10527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Start BLE advertising. 10627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 10727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param client Advertise client. 10827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 10927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void startAdvertising(AdvertiseClient client) { 11027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client == null) { 11127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 11227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 11327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Message message = new Message(); 11427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.what = MSG_START_ADVERTISING; 11527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.obj = client; 11627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mHandler.sendMessage(message); 11727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 11827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 11927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 12027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Stop BLE advertising. 12127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 12227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void stopAdvertising(AdvertiseClient client) { 12327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client == null) { 12427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 12527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 12627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Message message = new Message(); 12727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.what = MSG_STOP_ADVERTISING; 12827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang message.obj = client; 12927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mHandler.sendMessage(message); 13027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 13127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 13227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 13327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Signals the callback is received. 13427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 13527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param clientIf Identifier for the client. 13627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param status Status of the callback. 13727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 13827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void callbackDone(int clientIf, int status) { 13927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (status == AdvertiseCallback.ADVERTISE_SUCCESS) { 14027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mLatch.countDown(); 14127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } else { 14227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note in failure case we'll wait for the latch to timeout(which takes 100ms) and 14327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // the mClientHandler thread will be blocked till timeout. 14427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 14527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 14627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 14727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 14827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Post callback status to app process. 14927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void postCallback(int clientIf, int status) { 15027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang try { 15118999c2cfd477050de0ca88c3a73458235d82656Wei Wang AdvertiseClient client = getAdvertiseClient(clientIf); 15218999c2cfd477050de0ca88c3a73458235d82656Wei Wang AdvertiseSettings settings = (client == null) ? null : client.settings; 15318999c2cfd477050de0ca88c3a73458235d82656Wei Wang boolean isStart = true; 15418999c2cfd477050de0ca88c3a73458235d82656Wei Wang mService.onMultipleAdvertiseCallback(clientIf, status, isStart, settings); 15527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } catch (RemoteException e) { 15627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang loge("failed onMultipleAdvertiseCallback", e); 15727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 15827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 15927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 16018999c2cfd477050de0ca88c3a73458235d82656Wei Wang private AdvertiseClient getAdvertiseClient(int clientIf) { 16118999c2cfd477050de0ca88c3a73458235d82656Wei Wang for (AdvertiseClient client : mAdvertiseClients) { 16218999c2cfd477050de0ca88c3a73458235d82656Wei Wang if (client.clientIf == clientIf) { 16318999c2cfd477050de0ca88c3a73458235d82656Wei Wang return client; 16418999c2cfd477050de0ca88c3a73458235d82656Wei Wang } 16518999c2cfd477050de0ca88c3a73458235d82656Wei Wang } 16618999c2cfd477050de0ca88c3a73458235d82656Wei Wang return null; 16718999c2cfd477050de0ca88c3a73458235d82656Wei Wang } 16818999c2cfd477050de0ca88c3a73458235d82656Wei Wang 16927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Handler class that handles BLE advertising operations. 17027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private class ClientHandler extends Handler { 17127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 17227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ClientHandler(Looper looper) { 17327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang super(looper); 17427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 17527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 17627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang @Override 17727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang public void handleMessage(Message msg) { 17827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang logd("message : " + msg.what); 17927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseClient client = (AdvertiseClient) msg.obj; 18027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang switch (msg.what) { 18127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case MSG_START_ADVERTISING: 18227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang handleStartAdvertising(client); 18327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang break; 18427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case MSG_STOP_ADVERTISING: 18527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang handleStopAdvertising(client); 18627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang break; 18727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 18827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Shouldn't happen. 18927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.e(TAG, "recieve an unknown message : " + msg.what); 19027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang break; 19127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 19227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 19327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 19427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void handleStartAdvertising(AdvertiseClient client) { 19527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Utils.enforceAdminPermission(mService); 19627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int clientIf = client.clientIf; 19727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (mAdvertiseClients.contains(clientIf)) { 19827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); 19927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 20027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 20127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 20227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (mAdvertiseClients.size() >= maxAdvertiseInstances()) { 20327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, 20427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS); 20527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 20627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 20727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!mAdvertiseNative.startAdverising(client)) { 20827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 20927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 21027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 21127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mAdvertiseClients.add(client); 21227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang postCallback(clientIf, AdvertiseCallback.ADVERTISE_SUCCESS); 21327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 21427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 21527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Handles stop advertising. 21627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void handleStopAdvertising(AdvertiseClient client) { 21727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Utils.enforceAdminPermission(mService); 21827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client == null) { 21927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 22027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 221039bf1606bddb3794fd6aa9adee704733f89544fWei Wang logd("stop advertise for client " + client.clientIf); 222039bf1606bddb3794fd6aa9adee704733f89544fWei Wang mAdvertiseNative.stopAdvertising(client); 223039bf1606bddb3794fd6aa9adee704733f89544fWei Wang if (client.appDied) { 224039bf1606bddb3794fd6aa9adee704733f89544fWei Wang logd("app died - unregistering client : " + client.clientIf); 225039bf1606bddb3794fd6aa9adee704733f89544fWei Wang mService.unregisterClient(client.clientIf); 226039bf1606bddb3794fd6aa9adee704733f89544fWei Wang } 22727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (mAdvertiseClients.contains(client)) { 22861b76fd94c45ee1909cde1d08a643fc031ef287fYicheng Fan mAdvertiseClients.remove(client); 22927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 23027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 23127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 23227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Returns maximum advertise instances supported by controller. 233a1664d61821a59145f8095a75373403a0c54244eWei Wang int maxAdvertiseInstances() { 23427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note numOfAdvtInstances includes the standard advertising instance. 23527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // TODO: remove - 1 once the stack is able to include standard instance for multiple 23627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // advertising. 237a1664d61821a59145f8095a75373403a0c54244eWei Wang if (mAdapterService.isMultiAdvertisementSupported()) { 238a1664d61821a59145f8095a75373403a0c54244eWei Wang return mAdapterService.getNumOfAdvertisementInstancesSupported() - 1; 239a1664d61821a59145f8095a75373403a0c54244eWei Wang } 240a1664d61821a59145f8095a75373403a0c54244eWei Wang if (mAdapterService.isPeripheralModeSupported()) { 241a1664d61821a59145f8095a75373403a0c54244eWei Wang return 1; 242a1664d61821a59145f8095a75373403a0c54244eWei Wang } 243a1664d61821a59145f8095a75373403a0c54244eWei Wang return 0; 24427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 24527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 24627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 24727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Class that wraps advertise native related constants, methods etc. 24827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private class AdvertiseNative { 24927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Advertise interval for different modes. 25027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_HIGH_MILLS = 1000; 25127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_MEDIUM_MILLS = 250; 25227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_LOW_MILLS = 100; 25327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 25427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Add some randomness to the advertising min/max interval so the controller can do some 25527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // optimization. 25627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_INTERVAL_DELTA_UNIT = 10; 25727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 25827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // The following constants should be kept the same as those defined in bt stack. 25927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_37 = 1 << 0; 26027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_38 = 1 << 1; 26127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_39 = 1 << 2; 26227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_CHANNEL_ALL = 26327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ADVERTISING_CHANNEL_37 | ADVERTISING_CHANNEL_38 | ADVERTISING_CHANNEL_39; 26427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 26527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_MIN = 0; 26627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_LOW = 1; 26727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_MID = 2; 26827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_UPPER = 3; 26927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note this is not exposed to the Java API. 27027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_TX_POWER_MAX = 4; 27127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 27227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Note we don't expose connectable directed advertising to API. 27327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_EVENT_TYPE_CONNECTABLE = 0; 27427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_EVENT_TYPE_SCANNABLE = 2; 27527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private static final int ADVERTISING_EVENT_TYPE_NON_CONNECTABLE = 3; 27627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 277a1664d61821a59145f8095a75373403a0c54244eWei Wang // TODO: Extract advertising logic into interface as we have multiple implementations now. 27827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang boolean startAdverising(AdvertiseClient client) { 279a1664d61821a59145f8095a75373403a0c54244eWei Wang if (!mAdapterService.isMultiAdvertisementSupported() && 280a1664d61821a59145f8095a75373403a0c54244eWei Wang !mAdapterService.isPeripheralModeSupported()) { 281a1664d61821a59145f8095a75373403a0c54244eWei Wang return false; 282a1664d61821a59145f8095a75373403a0c54244eWei Wang } 283a1664d61821a59145f8095a75373403a0c54244eWei Wang if (mAdapterService.isMultiAdvertisementSupported()) { 284a1664d61821a59145f8095a75373403a0c54244eWei Wang return startMultiAdvertising(client); 285a1664d61821a59145f8095a75373403a0c54244eWei Wang } 286a1664d61821a59145f8095a75373403a0c54244eWei Wang return startSingleAdvertising(client); 287a1664d61821a59145f8095a75373403a0c54244eWei Wang } 288a1664d61821a59145f8095a75373403a0c54244eWei Wang 289a1664d61821a59145f8095a75373403a0c54244eWei Wang boolean startMultiAdvertising(AdvertiseClient client) { 290a1664d61821a59145f8095a75373403a0c54244eWei Wang logd("starting multi advertising"); 29127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang resetCountDownLatch(); 292a1664d61821a59145f8095a75373403a0c54244eWei Wang enableAdvertising(client); 29327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!waitForCallback()) { 29427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 29527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 29627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang resetCountDownLatch(); 297a1664d61821a59145f8095a75373403a0c54244eWei Wang setAdvertisingData(client, client.advertiseData, false); 29827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!waitForCallback()) { 29927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 30027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 30127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (client.scanResponse != null) { 30227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang resetCountDownLatch(); 303a1664d61821a59145f8095a75373403a0c54244eWei Wang setAdvertisingData(client, client.scanResponse, true); 30427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (!waitForCallback()) { 30527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 30627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 30727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 30827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return true; 30927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 31027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 311a1664d61821a59145f8095a75373403a0c54244eWei Wang boolean startSingleAdvertising(AdvertiseClient client) { 312a1664d61821a59145f8095a75373403a0c54244eWei Wang logd("starting single advertising"); 313a1664d61821a59145f8095a75373403a0c54244eWei Wang resetCountDownLatch(); 314a1664d61821a59145f8095a75373403a0c54244eWei Wang enableAdvertising(client); 315a1664d61821a59145f8095a75373403a0c54244eWei Wang if (!waitForCallback()) { 316a1664d61821a59145f8095a75373403a0c54244eWei Wang return false; 317a1664d61821a59145f8095a75373403a0c54244eWei Wang } 318a1664d61821a59145f8095a75373403a0c54244eWei Wang setAdvertisingData(client, client.advertiseData, false); 319a1664d61821a59145f8095a75373403a0c54244eWei Wang return true; 320a1664d61821a59145f8095a75373403a0c54244eWei Wang } 321a1664d61821a59145f8095a75373403a0c54244eWei Wang 32227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang void stopAdvertising(AdvertiseClient client) { 323a1664d61821a59145f8095a75373403a0c54244eWei Wang if (mAdapterService.isMultiAdvertisementSupported()) { 324a1664d61821a59145f8095a75373403a0c54244eWei Wang gattClientDisableAdvNative(client.clientIf); 325a1664d61821a59145f8095a75373403a0c54244eWei Wang } else { 326a1664d61821a59145f8095a75373403a0c54244eWei Wang gattAdvertiseNative(client.clientIf, false); 327a1664d61821a59145f8095a75373403a0c54244eWei Wang try { 328a1664d61821a59145f8095a75373403a0c54244eWei Wang mService.onAdvertiseInstanceDisabled( 329a1664d61821a59145f8095a75373403a0c54244eWei Wang AdvertiseCallback.ADVERTISE_SUCCESS, client.clientIf); 330a1664d61821a59145f8095a75373403a0c54244eWei Wang } catch (RemoteException e) { 331a1664d61821a59145f8095a75373403a0c54244eWei Wang Log.d(TAG, "failed onAdvertiseInstanceDisabled", e); 332a1664d61821a59145f8095a75373403a0c54244eWei Wang } 333a1664d61821a59145f8095a75373403a0c54244eWei Wang } 33427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 33527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 33627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void resetCountDownLatch() { 33727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang mLatch = new CountDownLatch(1); 33827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 33927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 34027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Returns true if mLatch reaches 0, false if timeout or interrupted. 34127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private boolean waitForCallback() { 34227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang try { 34327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return mLatch.await(OPERATION_TIME_OUT_MILLIS, TimeUnit.MILLISECONDS); 34427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } catch (InterruptedException e) { 34527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return false; 34627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 34727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 34827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 34927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void enableAdvertising(AdvertiseClient client) { 35027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int clientIf = client.clientIf; 35127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int minAdvertiseUnit = (int) getAdvertisingIntervalUnit(client.settings); 35227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int maxAdvertiseUnit = minAdvertiseUnit + ADVERTISING_INTERVAL_DELTA_UNIT; 35327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int advertiseEventType = getAdvertisingEventType(client); 35427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int txPowerLevel = getTxPowerLevel(client.settings); 355db0920ed7d9ef5385e36dfa922f351e4e6556a3eWei Wang int advertiseTimeoutSeconds = (int) TimeUnit.MILLISECONDS.toSeconds( 356db0920ed7d9ef5385e36dfa922f351e4e6556a3eWei Wang client.settings.getTimeout()); 357a1664d61821a59145f8095a75373403a0c54244eWei Wang if (mAdapterService.isMultiAdvertisementSupported()) { 358a1664d61821a59145f8095a75373403a0c54244eWei Wang gattClientEnableAdvNative( 359a1664d61821a59145f8095a75373403a0c54244eWei Wang clientIf, 360a1664d61821a59145f8095a75373403a0c54244eWei Wang minAdvertiseUnit, maxAdvertiseUnit, 361a1664d61821a59145f8095a75373403a0c54244eWei Wang advertiseEventType, 362a1664d61821a59145f8095a75373403a0c54244eWei Wang ADVERTISING_CHANNEL_ALL, 363a1664d61821a59145f8095a75373403a0c54244eWei Wang txPowerLevel, 364a1664d61821a59145f8095a75373403a0c54244eWei Wang advertiseTimeoutSeconds); 365a1664d61821a59145f8095a75373403a0c54244eWei Wang } else { 366a1664d61821a59145f8095a75373403a0c54244eWei Wang gattAdvertiseNative(client.clientIf, true); 367a1664d61821a59145f8095a75373403a0c54244eWei Wang } 36827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 36927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 370a1664d61821a59145f8095a75373403a0c54244eWei Wang private void setAdvertisingData(AdvertiseClient client, AdvertiseData data, 371a1664d61821a59145f8095a75373403a0c54244eWei Wang boolean isScanResponse) { 37227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (data == null) { 37327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return; 37427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 37586c292ab0f0fed25345a2eaef0fd92ff9c72a9e5Wei Wang boolean includeName = data.getIncludeDeviceName(); 37627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang boolean includeTxPower = data.getIncludeTxPowerLevel(); 37727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int appearance = 0; 378bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] manufacturerData = getManufacturerData(data); 37927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 380bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] serviceData = getServiceData(data); 38127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang byte[] serviceUuids; 38227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (data.getServiceUuids() == null) { 38327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang serviceUuids = new byte[0]; 38427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } else { 38527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang ByteBuffer advertisingUuidBytes = ByteBuffer.allocate( 38627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang data.getServiceUuids().size() * 16) 38727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang .order(ByteOrder.LITTLE_ENDIAN); 38827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang for (ParcelUuid parcelUuid : data.getServiceUuids()) { 38927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang UUID uuid = parcelUuid.getUuid(); 390bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Least significant bits first as the advertising UUID should be in 39127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // little-endian. 39227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang advertisingUuidBytes.putLong(uuid.getLeastSignificantBits()) 39327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang .putLong(uuid.getMostSignificantBits()); 39427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 39527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang serviceUuids = advertisingUuidBytes.array(); 39627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 397a1664d61821a59145f8095a75373403a0c54244eWei Wang if (mAdapterService.isMultiAdvertisementSupported()) { 398a1664d61821a59145f8095a75373403a0c54244eWei Wang gattClientSetAdvDataNative(client.clientIf, isScanResponse, includeName, 399a1664d61821a59145f8095a75373403a0c54244eWei Wang includeTxPower, appearance, 400a1664d61821a59145f8095a75373403a0c54244eWei Wang manufacturerData, serviceData, serviceUuids); 401a1664d61821a59145f8095a75373403a0c54244eWei Wang } else { 402a1664d61821a59145f8095a75373403a0c54244eWei Wang gattSetAdvDataNative(client.clientIf, isScanResponse, includeName, 403a1664d61821a59145f8095a75373403a0c54244eWei Wang includeTxPower, 0, 0, appearance, 404a1664d61821a59145f8095a75373403a0c54244eWei Wang manufacturerData, serviceData, serviceUuids); 405a1664d61821a59145f8095a75373403a0c54244eWei Wang } 40627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 40727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 408bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Combine manufacturer id and manufacturer data. 409bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang private byte[] getManufacturerData(AdvertiseData advertiseData) { 410e34b91565499994a4b04a1014432c8f90678972aWei Wang if (advertiseData.getManufacturerSpecificData().size() == 0) { 411bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return new byte[0]; 412bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 413e34b91565499994a4b04a1014432c8f90678972aWei Wang int manufacturerId = advertiseData.getManufacturerSpecificData().keyAt(0); 414e34b91565499994a4b04a1014432c8f90678972aWei Wang byte[] manufacturerData = advertiseData.getManufacturerSpecificData().get( 415e34b91565499994a4b04a1014432c8f90678972aWei Wang manufacturerId); 416bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang int dataLen = 2 + (manufacturerData == null ? 0 : manufacturerData.length); 417bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] concated = new byte[dataLen]; 418bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // / First two bytes are manufacturer id in little-endian. 419bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[0] = (byte) (manufacturerId & 0xFF); 420bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[1] = (byte) ((manufacturerId >> 8) & 0xFF); 421bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang if (manufacturerData != null) { 422bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang System.arraycopy(manufacturerData, 0, concated, 2, manufacturerData.length); 423bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 424bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return concated; 425bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 426bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang 427bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Combine service UUID and service data. 428bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang private byte[] getServiceData(AdvertiseData advertiseData) { 429e34b91565499994a4b04a1014432c8f90678972aWei Wang if (advertiseData.getServiceData().isEmpty()) { 430bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return new byte[0]; 431bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 432e34b91565499994a4b04a1014432c8f90678972aWei Wang ParcelUuid uuid = advertiseData.getServiceData().keySet().iterator().next(); 433e34b91565499994a4b04a1014432c8f90678972aWei Wang byte[] serviceData = advertiseData.getServiceData().get(uuid); 434bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang int dataLen = 2 + (serviceData == null ? 0 : serviceData.length); 435bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang byte[] concated = new byte[dataLen]; 436bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // Extract 16 bit UUID value. 437bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang int uuidValue = BluetoothUuid.getServiceIdentifierFromParcelUuid( 438e34b91565499994a4b04a1014432c8f90678972aWei Wang uuid); 439bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang // First two bytes are service data UUID in little-endian. 440bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[0] = (byte) (uuidValue & 0xFF); 441bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang concated[1] = (byte) ((uuidValue >> 8) & 0xFF); 442bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang if (serviceData != null) { 443bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang System.arraycopy(serviceData, 0, concated, 2, serviceData.length); 444bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 445bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang return concated; 446bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang } 447bebb0fe84fe06a47bd88cdfb9cba8ffe4d2c463aWei Wang 44827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Convert settings tx power level to stack tx power level. 44927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private int getTxPowerLevel(AdvertiseSettings settings) { 45027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang switch (settings.getTxPowerLevel()) { 45127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW: 45227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_MIN; 45327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_LOW: 45427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_LOW; 45527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM: 45627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_MID; 45727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_TX_POWER_HIGH: 45827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_UPPER; 45927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 46027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Shouldn't happen, just in case. 46127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_TX_POWER_MID; 46227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 46327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 46427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 46527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Convert advertising event type to stack values. 46627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private int getAdvertisingEventType(AdvertiseClient client) { 46727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang AdvertiseSettings settings = client.settings; 468db0920ed7d9ef5385e36dfa922f351e4e6556a3eWei Wang if (settings.isConnectable()) { 46927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return ADVERTISING_EVENT_TYPE_CONNECTABLE; 47027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 47127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return client.scanResponse == null ? ADVERTISING_EVENT_TYPE_NON_CONNECTABLE 47227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang : ADVERTISING_EVENT_TYPE_SCANNABLE; 47327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 47427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 47527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Convert advertising milliseconds to advertising units(one unit is 0.625 millisecond). 47627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private long getAdvertisingIntervalUnit(AdvertiseSettings settings) { 47727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang switch (settings.getMode()) { 47827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_MODE_LOW_POWER: 47996509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang return Utils.millsToUnit(ADVERTISING_INTERVAL_HIGH_MILLS); 48027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_MODE_BALANCED: 48196509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang return Utils.millsToUnit(ADVERTISING_INTERVAL_MEDIUM_MILLS); 48227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY: 48396509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang return Utils.millsToUnit(ADVERTISING_INTERVAL_LOW_MILLS); 48427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 48527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Shouldn't happen, just in case. 48696509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang return Utils.millsToUnit(ADVERTISING_INTERVAL_HIGH_MILLS); 48727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 48827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 48927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 49027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang // Native functions 49127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientDisableAdvNative(int client_if); 49227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 49327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientEnableAdvNative(int client_if, 49427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int min_interval, int max_interval, int adv_type, int chnl_map, 495c1512abbe9bb60c94c5f46e90918983d1514c8e3Andre Eisenbach int tx_power, int timeout_s); 49627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 49727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientUpdateAdvNative(int client_if, 49827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int min_interval, int max_interval, int adv_type, int chnl_map, 499c1512abbe9bb60c94c5f46e90918983d1514c8e3Andre Eisenbach int tx_power, int timeout_s); 50027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 50127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private native void gattClientSetAdvDataNative(int client_if, 50227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang boolean set_scan_rsp, boolean incl_name, boolean incl_txpower, int appearance, 50327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang byte[] manufacturer_data, byte[] service_data, byte[] service_uuid); 504a1664d61821a59145f8095a75373403a0c54244eWei Wang 505a1664d61821a59145f8095a75373403a0c54244eWei Wang private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 506a1664d61821a59145f8095a75373403a0c54244eWei Wang boolean inclTxPower, int minSlaveConnectionInterval, int maxSlaveConnectionInterval, 507a1664d61821a59145f8095a75373403a0c54244eWei Wang int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid); 508a1664d61821a59145f8095a75373403a0c54244eWei Wang 509a1664d61821a59145f8095a75373403a0c54244eWei Wang private native void gattAdvertiseNative(int client_if, boolean start); 51027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 51127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 51227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void logd(String s) { 51327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (DBG) { 51427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.d(TAG, s); 51527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 51627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 51727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 51827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang private void loge(String s, Exception e) { 51927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.e(TAG, s, e); 52027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 52127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 52227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang} 523