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