/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.gatt;

import static android.content.pm.PackageManager.PERMISSION_GRANTED;

import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.IAdvertisingSetCallback;
import android.bluetooth.le.IPeriodicAdvertisingCallback;
import android.bluetooth.le.IScannerCallback;
import android.bluetooth.le.PeriodicAdvertisingParameters;
import android.bluetooth.le.ResultStorageDescriptor;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.companion.ICompanionDeviceManager;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.Log;

import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AbstractionLayer;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.util.NumberUtils;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Provides Bluetooth Gatt profile, as a service in
 * the Bluetooth application.
 * @hide
 */
public class GattService extends ProfileService {
    private static final boolean DBG = GattServiceConfig.DBG;
    private static final boolean VDBG = GattServiceConfig.VDBG;
    private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService";
    private static final String UUID_SUFFIX = "-0000-1000-8000-00805f9b34fb";
    private static final String UUID_ZERO_PAD = "00000000";

    static final int SCAN_FILTER_ENABLED = 1;
    static final int SCAN_FILTER_MODIFIED = 2;

    private static final int MAC_ADDRESS_LENGTH = 6;
    // Batch scan related constants.
    private static final int TRUNCATED_RESULT_SIZE = 11;
    private static final int TIME_STAMP_LENGTH = 2;

    // onFoundLost related constants
    private static final int ADVT_STATE_ONFOUND = 0;
    private static final int ADVT_STATE_ONLOST = 1;

    private static final int ET_LEGACY_MASK = 0x10;

    private static final UUID HID_SERVICE_UUID =
            UUID.fromString("00001812-0000-1000-8000-00805F9B34FB");

    private static final UUID[] HID_UUIDS = {
            UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
            UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
            UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
            UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB")
    };

    private static final UUID ANDROID_TV_REMOTE_SERVICE_UUID =
            UUID.fromString("AB5E0001-5A21-4F05-BC7D-AF01F617B664");

    private static final UUID FIDO_SERVICE_UUID =
            UUID.fromString("0000FFFD-0000-1000-8000-00805F9B34FB"); // U2F

    /**
     * Keep the arguments passed in for the PendingIntent.
     */
    class PendingIntentInfo {
        public PendingIntent intent;
        public ScanSettings settings;
        public List<ScanFilter> filters;
        public String callingPackage;

        @Override
        public boolean equals(Object other) {
            if (!(other instanceof PendingIntentInfo)) {
                return false;
            }
            return intent.equals(((PendingIntentInfo) other).intent);
        }
    }

    /**
     * List of our registered scanners.
     */
    class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {}

    ScannerMap mScannerMap = new ScannerMap();

    /**
     * List of our registered clients.
     */
    class ClientMap extends ContextMap<IBluetoothGattCallback, Void> {}

    ClientMap mClientMap = new ClientMap();

    /**
     * List of our registered server apps.
     */
    class ServerMap extends ContextMap<IBluetoothGattServerCallback, Void> {}

    ServerMap mServerMap = new ServerMap();

    /**
     * Server handle map.
     */
    HandleMap mHandleMap = new HandleMap();
    private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>();

    private int mMaxScanFilters;

    private static final int NUM_SCAN_EVENTS_KEPT = 20;

    /**
     * Internal list of scan events to use with the proto
     */
    private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents =
            new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT);

    /**
     * Set of restricted (which require a BLUETOOTH_PRIVILEGED permission) handles per connectionId.
     */
    private final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>();

    private BluetoothAdapter mAdapter;
    private AdvertiseManager mAdvertiseManager;
    private PeriodicScanManager mPeriodicScanManager;
    private ScanManager mScanManager;
    private AppOpsManager mAppOps;
    private ICompanionDeviceManager mCompanionManager;
    private String mExposureNotificationPackage;

    private static GattService sGattService;

    /**
     * Reliable write queue
     */
    private Set<String> mReliableQueue = new HashSet<String>();

    static {
        classInitNative();
    }

    @Override
    protected IProfileServiceBinder initBinder() {
        return new BluetoothGattBinder(this);
    }

    @Override
    protected boolean start() {
        if (DBG) {
            Log.d(TAG, "start()");
        }
        mExposureNotificationPackage = getString(R.string.exposure_notification_package);
        Settings.Global.putInt(
                getContentResolver(), "bluetooth_sanitized_exposure_notification_supported", 1);
        initializeNative();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mCompanionManager = ICompanionDeviceManager.Stub.asInterface(
                ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
        mAppOps = getSystemService(AppOpsManager.class);
        mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService());
        mAdvertiseManager.start();

        mScanManager = new ScanManager(this);
        mScanManager.start();

        mPeriodicScanManager = new PeriodicScanManager(AdapterService.getAdapterService());
        mPeriodicScanManager.start();

        setGattService(this);
        return true;
    }

    @Override
    protected boolean stop() {
        if (DBG) {
            Log.d(TAG, "stop()");
        }
        setGattService(null);
        mScannerMap.clear();
        mClientMap.clear();
        mServerMap.clear();
        mHandleMap.clear();
        mReliableQueue.clear();
        if (mAdvertiseManager != null) {
            mAdvertiseManager.cleanup();
        }
        if (mScanManager != null) {
            mScanManager.cleanup();
        }
        if (mPeriodicScanManager != null) {
            mPeriodicScanManager.cleanup();
        }
        return true;
    }

    @Override
    protected void cleanup() {
        if (DBG) {
            Log.d(TAG, "cleanup()");
        }
        cleanupNative();
        if (mAdvertiseManager != null) {
            mAdvertiseManager.cleanup();
        }
        if (mScanManager != null) {
            mScanManager.cleanup();
        }
        if (mPeriodicScanManager != null) {
            mPeriodicScanManager.cleanup();
        }
    }


    /**
     * Get the current instance of {@link GattService}
     *
     * @return current instance of {@link GattService}
     */
    @VisibleForTesting
    public static synchronized GattService getGattService() {
        if (sGattService == null) {
            Log.w(TAG, "getGattService(): service is null");
            return null;
        }
        if (!sGattService.isAvailable()) {
            Log.w(TAG, "getGattService(): service is not available");
            return null;
        }
        return sGattService;
    }

    private static synchronized void setGattService(GattService instance) {
        if (DBG) {
            Log.d(TAG, "setGattService(): set to: " + instance);
        }
        sGattService = instance;
    }

    private boolean permissionCheck(UUID characteristicUuid) {
        return !isHidCharUuid(characteristicUuid)
                || (checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)
                        == PERMISSION_GRANTED);
    }

    private boolean permissionCheck(int connId, int handle) {
        Set<Integer> restrictedHandles = mRestrictedHandles.get(connId);
        if (restrictedHandles == null || !restrictedHandles.contains(handle)) {
            return true;
        }

        return (checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)
                == PERMISSION_GRANTED);
    }

    private boolean permissionCheck(ClientMap.App app, int connId, int handle) {
        Set<Integer> restrictedHandles = mRestrictedHandles.get(connId);
        if (restrictedHandles == null || !restrictedHandles.contains(handle)) {
            return true;
        }

        if (!app.hasBluetoothPrivilegedPermission
                && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)== PERMISSION_GRANTED) {
            app.hasBluetoothPrivilegedPermission = true;
        }

        return app.hasBluetoothPrivilegedPermission;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (GattDebugUtils.handleDebugAction(this, intent)) {
            return Service.START_NOT_STICKY;
        }
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * DeathReceipient handlers used to unregister applications that
     * disconnect ungracefully (ie. crash or forced close).
     */

    class ScannerDeathRecipient implements IBinder.DeathRecipient {
        int mScannerId;

        ScannerDeathRecipient(int scannerId) {
            mScannerId = scannerId;
        }

        @Override
        public void binderDied() {
            if (DBG) {
                Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!");
            }

            ScanClient client = getScanClient(mScannerId);
            if (client != null) {
                client.appDied = true;
                stopScan(client.scannerId);
            }
        }

        private ScanClient getScanClient(int clientIf) {
            for (ScanClient client : mScanManager.getRegularScanQueue()) {
                if (client.scannerId == clientIf) {
                    return client;
                }
            }
            for (ScanClient client : mScanManager.getBatchScanQueue()) {
                if (client.scannerId == clientIf) {
                    return client;
                }
            }
            return null;
        }
    }

    class ServerDeathRecipient implements IBinder.DeathRecipient {
        int mAppIf;

        ServerDeathRecipient(int appIf) {
            mAppIf = appIf;
        }

        @Override
        public void binderDied() {
            if (DBG) {
                Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!");
            }
            unregisterServer(mAppIf);
        }
    }

    class ClientDeathRecipient implements IBinder.DeathRecipient {
        int mAppIf;

        ClientDeathRecipient(int appIf) {
            mAppIf = appIf;
        }

        @Override
        public void binderDied() {
            if (DBG) {
                Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!");
            }
            unregisterClient(mAppIf);
        }
    }

    /**
     * Handlers for incoming service calls
     */
    private static class BluetoothGattBinder extends IBluetoothGatt.Stub
            implements IProfileServiceBinder {
        private GattService mService;

        BluetoothGattBinder(GattService svc) {
            mService = svc;
        }

        @Override
        public void cleanup() {
            mService = null;
        }

        private GattService getService() {
            if (mService != null && mService.isAvailable()) {
                return mService;
            }
            Log.e(TAG, "getService() - Service requested, but not available!");
            return null;
        }

        @Override
        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
            GattService service = getService();
            if (service == null) {
                return new ArrayList<BluetoothDevice>();
            }
            return service.getDevicesMatchingConnectionStates(states);
        }

        @Override
        public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, boolean eatt_support) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.registerClient(uuid.getUuid(), callback, eatt_support);
        }

        @Override
        public void unregisterClient(int clientIf) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.unregisterClient(clientIf);
        }

        @Override
        public void registerScanner(IScannerCallback callback, WorkSource workSource)
                throws RemoteException {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.registerScanner(callback, workSource);
        }

        @Override
        public void unregisterScanner(int scannerId) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.unregisterScanner(scannerId);
        }

        @Override
        public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
                List storages, String callingPackage, String callingFeatureId) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.startScan(scannerId, settings, filters, storages, callingPackage,
                    callingFeatureId);
        }

        @Override
        public void startScanForIntent(PendingIntent intent, ScanSettings settings,
                List<ScanFilter> filters, String callingPackage, String callingFeatureId)
                throws RemoteException {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.registerPiAndStartScan(intent, settings, filters, callingPackage,
                    callingFeatureId);
        }

        @Override
        public void stopScanForIntent(PendingIntent intent, String callingPackage)
                throws RemoteException {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.stopScan(intent, callingPackage);
        }

        @Override
        public void stopScan(int scannerId) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.stopScan(scannerId);
        }

        @Override
        public void flushPendingBatchResults(int scannerId) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.flushPendingBatchResults(scannerId);
        }

        @Override
        public void clientConnect(int clientIf, String address, boolean isDirect, int transport,
                boolean opportunistic, int phy) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.clientConnect(clientIf, address, isDirect, transport, opportunistic, phy);
        }

        @Override
        public void clientDisconnect(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.clientDisconnect(clientIf, address);
        }

        @Override
        public void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy,
                int phyOptions) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions);
        }

        @Override
        public void clientReadPhy(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.clientReadPhy(clientIf, address);
        }

        @Override
        public void refreshDevice(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.refreshDevice(clientIf, address);
        }

        @Override
        public void discoverServices(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.discoverServices(clientIf, address);
        }

        @Override
        public void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.discoverServiceByUuid(clientIf, address, uuid.getUuid());
        }

        @Override
        public void readCharacteristic(int clientIf, String address, int handle, int authReq) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.readCharacteristic(clientIf, address, handle, authReq);
        }

        @Override
        public void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid,
                int startHandle, int endHandle, int authReq) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.readUsingCharacteristicUuid(clientIf, address, uuid.getUuid(), startHandle,
                    endHandle, authReq);
        }

        @Override
        public void writeCharacteristic(int clientIf, String address, int handle, int writeType,
                int authReq, byte[] value) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value);
        }

        @Override
        public void readDescriptor(int clientIf, String address, int handle, int authReq) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.readDescriptor(clientIf, address, handle, authReq);
        }

        @Override
        public void writeDescriptor(int clientIf, String address, int handle, int authReq,
                byte[] value) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.writeDescriptor(clientIf, address, handle, authReq, value);
        }

        @Override
        public void beginReliableWrite(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.beginReliableWrite(clientIf, address);
        }

        @Override
        public void endReliableWrite(int clientIf, String address, boolean execute) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.endReliableWrite(clientIf, address, execute);
        }

        @Override
        public void registerForNotification(int clientIf, String address, int handle,
                boolean enable) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.registerForNotification(clientIf, address, handle, enable);
        }

        @Override
        public void readRemoteRssi(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.readRemoteRssi(clientIf, address);
        }

        @Override
        public void configureMTU(int clientIf, String address, int mtu) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.configureMTU(clientIf, address, mtu);
        }

        @Override
        public void connectionParameterUpdate(int clientIf, String address,
                int connectionPriority) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.connectionParameterUpdate(clientIf, address, connectionPriority);
        }

        @Override
        public void leConnectionUpdate(int clientIf, String address,
                int minConnectionInterval, int maxConnectionInterval,
                int peripheralLatency, int supervisionTimeout,
                int minConnectionEventLen, int maxConnectionEventLen) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.leConnectionUpdate(clientIf, address, minConnectionInterval,
                                       maxConnectionInterval, peripheralLatency,
                                       supervisionTimeout, minConnectionEventLen,
                                       maxConnectionEventLen);
        }

        @Override
        public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback,
                                   boolean eatt_support) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.registerServer(uuid.getUuid(), callback, eatt_support);
        }

        @Override
        public void unregisterServer(int serverIf) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.unregisterServer(serverIf);
        }

        @Override
        public void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.serverConnect(serverIf, address, isDirect, transport);
        }

        @Override
        public void serverDisconnect(int serverIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.serverDisconnect(serverIf, address);
        }

        @Override
        public void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy,
                int phyOptions) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions);
        }

        @Override
        public void serverReadPhy(int clientIf, String address) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.serverReadPhy(clientIf, address);
        }

        @Override
        public void addService(int serverIf, BluetoothGattService svc) {
            GattService service = getService();
            if (service == null) {
                return;
            }

            service.addService(serverIf, svc);
        }

        @Override
        public void removeService(int serverIf, int handle) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.removeService(serverIf, handle);
        }

        @Override
        public void clearServices(int serverIf) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.clearServices(serverIf);
        }

        @Override
        public void sendResponse(int serverIf, String address, int requestId, int status,
                int offset, byte[] value) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.sendResponse(serverIf, address, requestId, status, offset, value);
        }

        @Override
        public void sendNotification(int serverIf, String address, int handle, boolean confirm,
                byte[] value) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.sendNotification(serverIf, address, handle, confirm, value);
        }

        @Override
        public void startAdvertisingSet(AdvertisingSetParameters parameters,
                AdvertiseData advertiseData, AdvertiseData scanResponse,
                PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData,
                int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
                    periodicData, duration, maxExtAdvEvents, callback);
        }

        @Override
        public void stopAdvertisingSet(IAdvertisingSetCallback callback) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.stopAdvertisingSet(callback);
        }

        @Override
        public void getOwnAddress(int advertiserId) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getOwnAddress(advertiserId);
        }

        @Override
        public void enableAdvertisingSet(int advertiserId, boolean enable, int duration,
                int maxExtAdvEvents) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);
        }

        @Override
        public void setAdvertisingData(int advertiserId, AdvertiseData data) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.setAdvertisingData(advertiserId, data);
        }

        @Override
        public void setScanResponseData(int advertiserId, AdvertiseData data) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.setScanResponseData(advertiserId, data);
        }

        @Override
        public void setAdvertisingParameters(int advertiserId,
                AdvertisingSetParameters parameters) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.setAdvertisingParameters(advertiserId, parameters);
        }

        @Override
        public void setPeriodicAdvertisingParameters(int advertiserId,
                PeriodicAdvertisingParameters parameters) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.setPeriodicAdvertisingParameters(advertiserId, parameters);
        }

        @Override
        public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.setPeriodicAdvertisingData(advertiserId, data);
        }

        @Override
        public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.setPeriodicAdvertisingEnable(advertiserId, enable);
        }

        @Override
        public void registerSync(ScanResult scanResult, int skip, int timeout,
                IPeriodicAdvertisingCallback callback) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.registerSync(scanResult, skip, timeout, callback);
        }

        @Override
        public void unregisterSync(IPeriodicAdvertisingCallback callback) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.unregisterSync(callback);
        }

        @Override
        public void disconnectAll() {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.disconnectAll();
        }

        @Override
        public void unregAll() {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.unregAll();
        }

        @Override
        public int numHwTrackFiltersAvailable() {
            GattService service = getService();
            if (service == null) {
                return 0;
            }
            return service.numHwTrackFiltersAvailable();
        }
    }

    ;

    /**************************************************************************
     * Callback functions - CLIENT
     *************************************************************************/

    // EN format defined here:
    // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf
    private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = new byte[] {
        // size 2, flag field, flags byte (value is not important)
        (byte) 0x02, (byte) 0x01
    };
    private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1;
    private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = new byte[] {
        // size 3, complete 16 bit UUID, EN UUID
        (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD,
        // size 23, data for 16 bit UUID, EN UUID
        (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD,
        // ...payload
    };
    private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2;

    private static boolean arrayStartsWith(byte[] array, byte[] prefix) {
        if (array.length < prefix.length) {
            return false;
        }
        for (int i = 0; i < prefix.length; i++) {
            if (prefix[i] != array[i]) {
                return false;
            }
        }
        return true;
    }

    ScanResult getSanitizedExposureNotification(ScanResult result) {
        ScanRecord record = result.getScanRecord();
        // Remove the flags part of the payload, if present
        if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH
                && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) {
            record = ScanRecord.parseFromBytes(
                    Arrays.copyOfRange(
                            record.getBytes(),
                            EXPOSURE_NOTIFICATION_FLAGS_LENGTH,
                            record.getBytes().length));
        }

        if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) {
            return null;
        }
        if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) {
            return null;
        }

        return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0);
    }

    void onScanResult(int eventType, int addressType, String address, int primaryPhy,
            int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt,
            byte[] advData) {
        if (VDBG) {
            Log.d(TAG, "onScanResult() - eventType=0x" + Integer.toHexString(eventType)
                    + ", addressType=" + addressType + ", address=" + address + ", primaryPhy="
                    + primaryPhy + ", secondaryPhy=" + secondaryPhy + ", advertisingSid=0x"
                    + Integer.toHexString(advertisingSid) + ", txPower=" + txPower + ", rssi="
                    + rssi + ", periodicAdvInt=0x" + Integer.toHexString(periodicAdvInt));
        }
        List<UUID> remoteUuids = parseUuids(advData);

        byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62);

        for (ScanClient client : mScanManager.getRegularScanQueue()) {
            if (client.uuids.length > 0) {
                int matches = 0;
                for (UUID search : client.uuids) {
                    for (UUID remote : remoteUuids) {
                        if (remote.equals(search)) {
                            ++matches;
                            break; // Only count 1st match in case of duplicates
                        }
                    }
                }

                if (matches < client.uuids.length) {
                    continue;
                }
            }

            ScannerMap.App app = mScannerMap.getById(client.scannerId);
            if (app == null) {
                continue;
            }

            BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);

            ScanSettings settings = client.settings;
            byte[] scanRecordData;
            // This is for compability with applications that assume fixed size scan data.
            if (settings.getLegacy()) {
                if ((eventType & ET_LEGACY_MASK) == 0) {
                    // If this is legacy scan, but nonlegacy result - skip.
                    continue;
                } else {
                    // Some apps are used to fixed-size advertise data.
                    scanRecordData = legacyAdvData;
                }
            } else {
                scanRecordData = advData;
            }

            ScanResult result =
                    new ScanResult(device, eventType, primaryPhy, secondaryPhy, advertisingSid,
                            txPower, rssi, periodicAdvInt,
                            ScanRecord.parseFromBytes(scanRecordData),
                            SystemClock.elapsedRealtimeNanos());
            boolean hasPermission = hasScanResultPermission(client);
            if (!hasPermission) {
                for (String associatedDevice : client.associatedDevices) {
                    if (associatedDevice.equalsIgnoreCase(address)) {
                        hasPermission = true;
                        break;
                    }
                }
            }
            if (!hasPermission && client.eligibleForSanitizedExposureNotification) {
                ScanResult sanitized = getSanitizedExposureNotification(result);
                if (sanitized != null) {
                    hasPermission = true;
                    result = sanitized;
                }
            }
            if (!hasPermission || !matchesFilters(client, result)) {
                continue;
            }

            if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) {
                continue;
            }

            try {
                app.appScanStats.addResult(client.scannerId);
                if (app.callback != null) {
                    app.callback.onScanResult(result);
                } else {
                    // Send the PendingIntent
                    ArrayList<ScanResult> results = new ArrayList<>();
                    results.add(result);
                    sendResultsByPendingIntent(app.info, results,
                            ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
                }
            } catch (RemoteException | PendingIntent.CanceledException e) {
                Log.e(TAG, "Exception: " + e);
                mScannerMap.remove(client.scannerId);
                mScanManager.stopScan(client.scannerId);
            }
        }
    }

    private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result,
            int callbackType, ScanClient client) {
        ArrayList<ScanResult> results = new ArrayList<>();
        results.add(result);
        try {
            sendResultsByPendingIntent(pii, results, callbackType);
        } catch (PendingIntent.CanceledException e) {
            stopScan(client.scannerId);
            unregisterScanner(client.scannerId);
        }
    }

    private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results,
            int callbackType) throws PendingIntent.CanceledException {
        Intent extrasIntent = new Intent();
        extrasIntent.putParcelableArrayListExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT,
                results);
        extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType);
        pii.intent.send(this, 0, extrasIntent);
    }

    private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode)
            throws PendingIntent.CanceledException {
        Intent extrasIntent = new Intent();
        extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode);
        pii.intent.send(this, 0, extrasIntent);
    }

    void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)
            throws RemoteException {
        UUID uuid = new UUID(uuidMsb, uuidLsb);
        if (DBG) {
            Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId
                    + ", status=" + status);
        }

        // First check the callback map
        ScannerMap.App cbApp = mScannerMap.getByUuid(uuid);
        if (cbApp != null) {
            if (status == 0) {
                cbApp.id = scannerId;
                // If app is callback based, setup a death recipient. App will initiate the start.
                // Otherwise, if PendingIntent based, start the scan directly.
                if (cbApp.callback != null) {
                    cbApp.linkToDeath(new ScannerDeathRecipient(scannerId));
                } else {
                    continuePiStartScan(scannerId, cbApp);
                }
            } else {
                mScannerMap.remove(scannerId);
            }
            if (cbApp.callback != null) {
                cbApp.callback.onScannerRegistered(status, scannerId);
            }
        }
    }

    /** Determines if the given scan client has the appropriate permissions to receive callbacks. */
    private boolean hasScanResultPermission(final ScanClient client) {
        if (client.hasNetworkSettingsPermission
                || client.hasNetworkSetupWizardPermission
                || client.hasScanWithoutLocationPermission) {
            return true;
        }
        return client.hasLocationPermission && !Utils.blockedByLocationOff(this, client.userHandle);
    }

    // Check if a scan record matches a specific filters.
    private boolean matchesFilters(ScanClient client, ScanResult scanResult) {
        if (client.filters == null || client.filters.isEmpty()) {
            return true;
        }
        for (ScanFilter filter : client.filters) {
            if (filter.matches(scanResult)) {
                return true;
            }
        }
        return false;
    }

    void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)
            throws RemoteException {
        UUID uuid = new UUID(uuidMsb, uuidLsb);
        if (DBG) {
            Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
        }
        ClientMap.App app = mClientMap.getByUuid(uuid);
        if (app != null) {
            if (status == 0) {
                app.id = clientIf;
                app.linkToDeath(new ClientDeathRecipient(clientIf));
            } else {
                mClientMap.remove(uuid);
            }
            app.callback.onClientRegistered(status, clientIf);
        }
    }

    void onConnected(int clientIf, int connId, int status, String address) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onConnected() - clientIf=" + clientIf + ", connId=" + connId + ", address="
                    + address);
        }

        if (status == 0) {
            mClientMap.addConnection(clientIf, connId, address);
        }
        ClientMap.App app = mClientMap.getById(clientIf);
        if (app != null) {
            app.callback.onClientConnectionState(status, clientIf,
                    (status == BluetoothGatt.GATT_SUCCESS), address);
        }
    }

    void onDisconnected(int clientIf, int connId, int status, String address)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG,
                    "onDisconnected() - clientIf=" + clientIf + ", connId=" + connId + ", address="
                            + address);
        }

        mClientMap.removeConnection(clientIf, connId);
        ClientMap.App app = mClientMap.getById(clientIf);
        if (app != null) {
            app.callback.onClientConnectionState(status, clientIf, false, address);
        }
    }

    void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status);
        }

        String address = mClientMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onPhyUpdate(address, txPhy, rxPhy, status);
    }

    void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG,
                    "onClientPhyRead() - address=" + address + ", status=" + status + ", clientIf="
                            + clientIf);
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.d(TAG, "onClientPhyRead() - no connection to " + address);
            return;
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onPhyRead(address, txPhy, rxPhy, status);
    }

    void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status);
        }

        String address = mClientMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
    }

    void onServiceChanged(int connId) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServiceChanged - connId=" + connId);
        }

        String address = mClientMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onServiceChanged(address);
    }

    void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status);
        }

        String address = mServerMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onPhyUpdate(address, txPhy, rxPhy, status);
    }

    void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status);
        }

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
        if (connId == null) {
            Log.d(TAG, "onServerPhyRead() - no connection to " + address);
            return;
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onPhyRead(address, txPhy, rxPhy, status);
    }

    void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status);
        }

        String address = mServerMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
    }

    void onSearchCompleted(int connId, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onSearchCompleted() - connId=" + connId + ", status=" + status);
        }
        // Gatt DB is ready!

        // This callback was called from the jni_workqueue thread. If we make request to the stack
        // on the same thread, it might cause deadlock. Schedule request on a new thread instead.
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                gattClientGetGattDbNative(connId);
            }
        });
        t.start();
    }

    GattDbElement getSampleGattDbElement() {
        return new GattDbElement();
    }

    void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (DBG) {
            Log.d(TAG, "onGetGattDb() - address=" + address);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null || app.callback == null) {
            Log.e(TAG, "app or callback is null");
            return;
        }

        List<BluetoothGattService> dbOut = new ArrayList<BluetoothGattService>();
        Set<Integer> restrictedIds = new HashSet<>();

        BluetoothGattService currSrvc = null;
        BluetoothGattCharacteristic currChar = null;
        boolean isRestrictedSrvc = false;
        boolean isHidSrvc = false;
        boolean isRestrictedChar = false;

        for (GattDbElement el : db) {
            switch (el.type) {
                case GattDbElement.TYPE_PRIMARY_SERVICE:
                case GattDbElement.TYPE_SECONDARY_SERVICE:
                    if (DBG) {
                        Log.d(TAG, "got service with UUID=" + el.uuid + " id: " + el.id);
                    }

                    currSrvc = new BluetoothGattService(el.uuid, el.id, el.type);
                    dbOut.add(currSrvc);
                    isRestrictedSrvc =
                            isFidoSrvcUuid(el.uuid) || isAndroidTvRemoteSrvcUuid(el.uuid);
                    isHidSrvc = isHidSrvcUuid(el.uuid);
                    if (isRestrictedSrvc) {
                        restrictedIds.add(el.id);
                    }
                    break;

                case GattDbElement.TYPE_CHARACTERISTIC:
                    if (DBG) {
                        Log.d(TAG, "got characteristic with UUID=" + el.uuid + " id: " + el.id);
                    }

                    currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0);
                    currSrvc.addCharacteristic(currChar);
                    isRestrictedChar = isRestrictedSrvc || (isHidSrvc && isHidCharUuid(el.uuid));
                    if (isRestrictedChar) {
                        restrictedIds.add(el.id);
                    }
                    break;

                case GattDbElement.TYPE_DESCRIPTOR:
                    if (DBG) {
                        Log.d(TAG, "got descriptor with UUID=" + el.uuid + " id: " + el.id);
                    }

                    currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0));
                    if (isRestrictedChar) {
                        restrictedIds.add(el.id);
                    }
                    break;

                case GattDbElement.TYPE_INCLUDED_SERVICE:
                    if (DBG) {
                        Log.d(TAG, "got included service with UUID=" + el.uuid + " id: " + el.id
                                + " startHandle: " + el.startHandle);
                    }

                    currSrvc.addIncludedService(
                            new BluetoothGattService(el.uuid, el.startHandle, el.type));
                    break;

                default:
                    Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid
                            + " id: " + el.id);
            }
        }

        if (!restrictedIds.isEmpty()) {
            mRestrictedHandles.put(connId, restrictedIds);
        }
        // Search is complete when there was error, or nothing more to process
        app.callback.onSearchComplete(address, dbOut, 0 /* status */);
    }

    void onRegisterForNotifications(int connId, int status, int registered, int handle) {
        String address = mClientMap.addressByConnId(connId);

        if (DBG) {
            Log.d(TAG, "onRegisterForNotifications() - address=" + address + ", status=" + status
                    + ", registered=" + registered + ", handle=" + handle);
        }
    }

    void onNotify(int connId, String address, int handle, boolean isNotify, byte[] data)
            throws RemoteException {

        if (VDBG) {
            Log.d(TAG, "onNotify() - address=" + address + ", handle=" + handle + ", length="
                    + data.length);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            if (!permissionCheck(app, connId, handle)) {
                Log.w(TAG, "onNotify() - permission check failed!");
                return;
            }
            app.callback.onNotify(address, handle, data);
        }
    }

    void onReadCharacteristic(int connId, int status, int handle, byte[] data)
            throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (VDBG) {
            Log.d(TAG, "onReadCharacteristic() - address=" + address + ", status=" + status
                    + ", length=" + data.length);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            app.callback.onCharacteristicRead(address, status, handle, data);
        }
    }

    void onWriteCharacteristic(int connId, int status, int handle) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (VDBG) {
            Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        if (!app.isCongested) {
            app.callback.onCharacteristicWrite(address, status, handle);
        } else {
            if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                status = BluetoothGatt.GATT_SUCCESS;
            }
            CallbackInfo callbackInfo = new CallbackInfo(address, status, handle);
            app.queueCallback(callbackInfo);
        }
    }

    void onExecuteCompleted(int connId, int status) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);
        if (VDBG) {
            Log.d(TAG, "onExecuteCompleted() - address=" + address + ", status=" + status);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            app.callback.onExecuteWrite(address, status);
        }
    }

    void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (VDBG) {
            Log.d(TAG,
                    "onReadDescriptor() - address=" + address + ", status=" + status + ", length="
                            + data.length);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            app.callback.onDescriptorRead(address, status, handle, data);
        }
    }

    void onWriteDescriptor(int connId, int status, int handle) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (VDBG) {
            Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            app.callback.onDescriptorWrite(address, status, handle);
        }
    }

    void onReadRemoteRssi(int clientIf, String address, int rssi, int status)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG,
                    "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + address + ", rssi="
                            + rssi + ", status=" + status);
        }

        ClientMap.App app = mClientMap.getById(clientIf);
        if (app != null) {
            app.callback.onReadRemoteRssi(address, rssi, status);
        }
    }

    void onScanFilterEnableDisabled(int action, int status, int clientIf) {
        if (DBG) {
            Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status
                    + ", action=" + action);
        }
        mScanManager.callbackDone(clientIf, status);
    }

    void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) {
        if (DBG) {
            Log.d(TAG,
                    "onScanFilterParamsConfigured() - clientIf=" + clientIf + ", status=" + status
                            + ", action=" + action + ", availableSpace=" + availableSpace);
        }
        mScanManager.callbackDone(clientIf, status);
    }

    void onScanFilterConfig(int action, int status, int clientIf, int filterType,
            int availableSpace) {
        if (DBG) {
            Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action
                    + " status = " + status + ", filterType=" + filterType + ", availableSpace="
                    + availableSpace);
        }

        mScanManager.callbackDone(clientIf, status);
    }

    void onBatchScanStorageConfigured(int status, int clientIf) {
        if (DBG) {
            Log.d(TAG,
                    "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status);
        }
        mScanManager.callbackDone(clientIf, status);
    }

    // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped.
    void onBatchScanStartStopped(int startStopAction, int status, int clientIf) {
        if (DBG) {
            Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf + ", status=" + status
                    + ", startStopAction=" + startStopAction);
        }
        mScanManager.callbackDone(clientIf, status);
    }

    void onBatchScanReports(int status, int scannerId, int reportType, int numRecords,
            byte[] recordData) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status
                    + ", reportType=" + reportType + ", numRecords=" + numRecords);
        }
        mScanManager.callbackDone(scannerId, status);
        Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData);
        if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
            // We only support single client for truncated mode.
            ScannerMap.App app = mScannerMap.getById(scannerId);
            if (app == null) {
                return;
            }
            if (app.callback != null) {
                app.callback.onBatchScanResults(new ArrayList<ScanResult>(results));
            } else {
                // PendingIntent based
                try {
                    sendResultsByPendingIntent(app.info, new ArrayList<ScanResult>(results),
                            ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
                } catch (PendingIntent.CanceledException e) {
                }
            }
        } else {
            for (ScanClient client : mScanManager.getFullBatchScanQueue()) {
                // Deliver results for each client.
                deliverBatchScan(client, results);
            }
        }
    }

    private void sendBatchScanResults(ScannerMap.App app, ScanClient client,
            ArrayList<ScanResult> results) {
        try {
            if (app.callback != null) {
                app.callback.onBatchScanResults(results);
            } else {
                sendResultsByPendingIntent(app.info, results,
                        ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
            }
        } catch (RemoteException | PendingIntent.CanceledException e) {
            Log.e(TAG, "Exception: " + e);
            mScannerMap.remove(client.scannerId);
            mScanManager.stopScan(client.scannerId);
        }
    }

    // Check and deliver scan results for different scan clients.
    private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults)
            throws RemoteException {
        ScannerMap.App app = mScannerMap.getById(client.scannerId);
        if (app == null) {
            return;
        }
        if (client.filters == null || client.filters.isEmpty()) {
            sendBatchScanResults(app, client, new ArrayList<ScanResult>(allResults));
            // TODO: Question to reviewer: Shouldn't there be a return here?
        }
        // Reconstruct the scan results.
        ArrayList<ScanResult> results = new ArrayList<ScanResult>();
        for (ScanResult scanResult : allResults) {
            if (matchesFilters(client, scanResult)) {
                results.add(scanResult);
            }
        }
        sendBatchScanResults(app, client, results);
    }

    private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType,
            byte[] batchRecord) {
        if (numRecords == 0) {
            return Collections.emptySet();
        }
        if (DBG) {
            Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos());
        }
        if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
            return parseTruncatedResults(numRecords, batchRecord);
        } else {
            return parseFullResults(numRecords, batchRecord);
        }
    }

    private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) {
        if (DBG) {
            Log.d(TAG, "batch record " + Arrays.toString(batchRecord));
        }
        Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
        long now = SystemClock.elapsedRealtimeNanos();
        for (int i = 0; i < numRecords; ++i) {
            byte[] record =
                    extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE);
            byte[] address = extractBytes(record, 0, 6);
            reverse(address);
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            int rssi = record[8];
            long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2));
            results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi,
                    timestampNanos));
        }
        return results;
    }

    @VisibleForTesting
    long parseTimestampNanos(byte[] data) {
        long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data);
        // Timestamp is in every 50 ms.
        return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50);
    }

    private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) {
        if (DBG) {
            Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord));
        }
        Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
        int position = 0;
        long now = SystemClock.elapsedRealtimeNanos();
        while (position < batchRecord.length) {
            byte[] address = extractBytes(batchRecord, position, 6);
            // TODO: remove temp hack.
            reverse(address);
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            position += 6;
            // Skip address type.
            position++;
            // Skip tx power level.
            position++;
            int rssi = batchRecord[position++];
            long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2));
            position += 2;

            // Combine advertise packet and scan response packet.
            int advertisePacketLen = batchRecord[position++];
            byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen);
            position += advertisePacketLen;
            int scanResponsePacketLen = batchRecord[position++];
            byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen);
            position += scanResponsePacketLen;
            byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen];
            System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen);
            System.arraycopy(scanResponseBytes, 0, scanRecord, advertisePacketLen,
                    scanResponsePacketLen);
            if (DBG) {
                Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord));
            }
            results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi,
                    timestampNanos));
        }
        return results;
    }

    // Reverse byte array.
    private void reverse(byte[] address) {
        int len = address.length;
        for (int i = 0; i < len / 2; ++i) {
            byte b = address[i];
            address[i] = address[len - 1 - i];
            address[len - 1 - i] = b;
        }
    }

    // Helper method to extract bytes from byte array.
    private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(scanRecord, start, bytes, 0, length);
        return bytes;
    }

    void onBatchScanThresholdCrossed(int clientIf) {
        if (DBG) {
            Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf);
        }
        flushPendingBatchResults(clientIf);
    }

    AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject(int clientIf, int advPktLen,
            byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState,
            int advInfoPresent, String address, int addrType, int txPower, int rssiValue,
            int timeStamp) {

        return new AdvtFilterOnFoundOnLostInfo(clientIf, advPktLen, advPkt, scanRspLen, scanRsp,
                filtIndex, advState, advInfoPresent, address, addrType, txPower, rssiValue,
                timeStamp);
    }

    void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf()
                    + " address = " + trackingInfo.getAddress() + " adv_state = "
                    + trackingInfo.getAdvState());
        }

        ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf());
        if (app == null || (app.callback == null && app.info == null)) {
            Log.e(TAG, "app or callback is null");
            return;
        }

        BluetoothDevice device =
                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(trackingInfo.getAddress());
        int advertiserState = trackingInfo.getAdvState();
        ScanResult result =
                new ScanResult(device, ScanRecord.parseFromBytes(trackingInfo.getResult()),
                        trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos());

        for (ScanClient client : mScanManager.getRegularScanQueue()) {
            if (client.scannerId == trackingInfo.getClientIf()) {
                ScanSettings settings = client.settings;
                if ((advertiserState == ADVT_STATE_ONFOUND) && (
                        (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
                                != 0)) {
                    if (app.callback != null) {
                        app.callback.onFoundOrLost(true, result);
                    } else {
                        sendResultByPendingIntent(app.info, result,
                                ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client);
                    }
                } else if ((advertiserState == ADVT_STATE_ONLOST) && (
                        (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST)
                                != 0)) {
                    if (app.callback != null) {
                        app.callback.onFoundOrLost(false, result);
                    } else {
                        sendResultByPendingIntent(app.info, result,
                                ScanSettings.CALLBACK_TYPE_MATCH_LOST, client);
                    }
                } else {
                    if (DBG) {
                        Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState
                                + " scannerId = " + client.scannerId + " callbackType "
                                + settings.getCallbackType());
                    }
                }
            }
        }
    }

    void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException {
        ScannerMap.App app = mScannerMap.getById(scannerId);
        if (app == null || app.callback == null) {
            Log.e(TAG, "Advertise app or callback is null");
            return;
        }
        if (DBG) {
            Log.d(TAG, "onScanParamSetupCompleted : " + status);
        }
    }

    // callback from ScanManager for dispatch of errors apps.
    void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException {
        ScannerMap.App app = mScannerMap.getById(scannerId);
        if (app == null || (app.callback == null && app.info == null)) {
            Log.e(TAG, "App or callback is null");
            return;
        }
        if (app.callback != null) {
            app.callback.onScanManagerErrorCallback(errorCode);
        } else {
            try {
                sendErrorByPendingIntent(app.info, errorCode);
            } catch (PendingIntent.CanceledException e) {
                Log.e(TAG, "Error sending error code via PendingIntent:" + e);
            }
        }
    }

    void onConfigureMTU(int connId, int status, int mtu) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (DBG) {
            Log.d(TAG,
                    "onConfigureMTU() address=" + address + ", status=" + status + ", mtu=" + mtu);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            app.callback.onConfigureMTU(address, mtu, status);
        }
    }

    void onClientCongestion(int connId, boolean congested) throws RemoteException {
        if (VDBG) {
            Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);

        if (app != null) {
            app.isCongested = congested;
            while (!app.isCongested) {
                CallbackInfo callbackInfo = app.popQueuedCallback();
                if (callbackInfo == null) {
                    return;
                }
                app.callback.onCharacteristicWrite(callbackInfo.address, callbackInfo.status,
                        callbackInfo.handle);
            }
        }
    }

    /**************************************************************************
     * GATT Service functions - Shared CLIENT/SERVER
     *************************************************************************/

    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, Integer>();

        // Add paired LE devices

        Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
        for (BluetoothDevice device : bondedDevices) {
            if (getDeviceType(device) != AbstractionLayer.BT_DEVICE_TYPE_BREDR) {
                deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED);
            }
        }

        // Add connected deviceStates

        Set<String> connectedDevices = new HashSet<String>();
        connectedDevices.addAll(mClientMap.getConnectedDevices());
        connectedDevices.addAll(mServerMap.getConnectedDevices());

        for (String address : connectedDevices) {
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            if (device != null) {
                deviceStates.put(device, BluetoothProfile.STATE_CONNECTED);
            }
        }

        // Create matching device sub-set

        List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();

        for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) {
            for (int state : states) {
                if (entry.getValue() == state) {
                    deviceList.add(entry.getKey());
                }
            }
        }

        return deviceList;
    }

    void registerScanner(IScannerCallback callback, WorkSource workSource) throws RemoteException {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        UUID uuid = UUID.randomUUID();
        if (DBG) {
            Log.d(TAG, "registerScanner() - UUID=" + uuid);
        }

        if (workSource != null) {
            enforceImpersonatationPermission();
        }

        AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid());
        if (app != null && app.isScanningTooFrequently()
                && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) {
            Log.e(TAG, "App '" + app.appName + "' is scanning too frequently");
            callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1);
            return;
        }

        mScannerMap.add(uuid, workSource, callback, null, this);
        mScanManager.registerScanner(uuid);
    }

    void unregisterScanner(int scannerId) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId);
        }
        mScannerMap.remove(scannerId);
        mScanManager.unregisterScanner(scannerId);
    }

    private List<String> getAssociatedDevices(String callingPackage, UserHandle userHandle) {
        if (mCompanionManager == null) {
            return new ArrayList<String>();
        }
        long identity = Binder.clearCallingIdentity();
        try {
            return mCompanionManager.getAssociations(
                    callingPackage, userHandle.getIdentifier());
        } catch (SecurityException se) {
            // Not an app with associated devices
        } catch (RemoteException re) {
            Log.e(TAG, "Cannot reach companion device service", re);
        } catch (Exception e) {
            Log.e(TAG, "Cannot check device associations for " + callingPackage, e);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
        return new ArrayList<String>();
    }

    void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
            List<List<ResultStorageDescriptor>> storages, String callingPackage,
            @Nullable String callingFeatureId) {
        if (DBG) {
            Log.d(TAG, "start scan with filters");
        }
        UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId());
        enforceAdminPermission();
        if (needsPrivilegedPermissionForScan(settings)) {
            enforcePrivilegedPermission();
        }
        final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages);
        scanClient.userHandle = UserHandle.of(UserHandle.getCallingUserId());
        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
        scanClient.eligibleForSanitizedExposureNotification =
                callingPackage.equals(mExposureNotificationPackage);
        scanClient.isQApp = Utils.isQApp(this, callingPackage);
        if (scanClient.isQApp) {
            scanClient.hasLocationPermission = Utils.checkCallerHasFineLocation(this, mAppOps,
                    callingPackage, callingFeatureId, scanClient.userHandle);
        } else {
            scanClient.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation(this,
                    mAppOps, callingPackage, callingFeatureId, scanClient.userHandle);
        }
        scanClient.hasNetworkSettingsPermission =
                Utils.checkCallerHasNetworkSettingsPermission(this);
        scanClient.hasNetworkSetupWizardPermission =
                Utils.checkCallerHasNetworkSetupWizardPermission(this);
        scanClient.hasScanWithoutLocationPermission =
                Utils.checkCallerHasScanWithoutLocationPermission(this);
        scanClient.associatedDevices = getAssociatedDevices(callingPackage, scanClient.userHandle);

        AppScanStats app = mScannerMap.getAppScanStatsById(scannerId);
        ScannerMap.App cbApp = mScannerMap.getById(scannerId);
        if (app != null) {
            scanClient.stats = app;
            boolean isFilteredScan = (filters != null) && !filters.isEmpty();
            boolean isCallbackScan = false;
            if (cbApp != null) {
                isCallbackScan = cbApp.callback != null;
            }
            app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId);
        }

        mScanManager.startScan(scanClient);
    }

    void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings,
            List<ScanFilter> filters, String callingPackage, @Nullable String callingFeatureId) {
        if (DBG) {
            Log.d(TAG, "start scan with filters, for PendingIntent");
        }
        enforceAdminPermission();
        if (needsPrivilegedPermissionForScan(settings)) {
            enforcePrivilegedPermission();
        }

        UUID uuid = UUID.randomUUID();
        if (DBG) {
            Log.d(TAG, "startScan(PI) - UUID=" + uuid);
        }
        PendingIntentInfo piInfo = new PendingIntentInfo();
        piInfo.intent = pendingIntent;
        piInfo.settings = settings;
        piInfo.filters = filters;
        piInfo.callingPackage = callingPackage;

        // Don't start scan if the Pi scan already in mScannerMap.
        if (mScannerMap.getByContextInfo(piInfo) != null) {
            Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap.");
            return;
        }

        ScannerMap.App app = mScannerMap.add(uuid, null, null, piInfo, this);
        app.mUserHandle = UserHandle.of(UserHandle.getCallingUserId());
        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
        app.mEligibleForSanitizedExposureNotification =
                callingPackage.equals(mExposureNotificationPackage);
        app.mIsQApp = Utils.isQApp(this, callingPackage);
        try {
            if (app.mIsQApp) {
                app.hasLocationPermission = Utils.checkCallerHasFineLocation(
                      this, mAppOps, callingPackage, callingFeatureId, app.mUserHandle);
            } else {
                app.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation(
                      this, mAppOps, callingPackage, callingFeatureId, app.mUserHandle);
            }
        } catch (SecurityException se) {
            // No need to throw here. Just mark as not granted.
            app.hasLocationPermission = false;
        }
        app.mHasNetworkSettingsPermission =
                Utils.checkCallerHasNetworkSettingsPermission(this);
        app.mHasNetworkSetupWizardPermission =
                Utils.checkCallerHasNetworkSetupWizardPermission(this);
        app.mHasScanWithoutLocationPermission =
                Utils.checkCallerHasScanWithoutLocationPermission(this);
        app.mAssociatedDevices = getAssociatedDevices(callingPackage, app.mUserHandle);
        mScanManager.registerScanner(uuid);
    }

    void continuePiStartScan(int scannerId, ScannerMap.App app) {
        final PendingIntentInfo piInfo = app.info;
        final ScanClient scanClient =
                new ScanClient(scannerId, piInfo.settings, piInfo.filters, null);
        scanClient.hasLocationPermission = app.hasLocationPermission;
        scanClient.userHandle = app.mUserHandle;
        scanClient.isQApp = app.mIsQApp;
        scanClient.eligibleForSanitizedExposureNotification =
                app.mEligibleForSanitizedExposureNotification;
        scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission;
        scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission;
        scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission;
        scanClient.associatedDevices = app.mAssociatedDevices;

        AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId);
        if (scanStats != null) {
            scanClient.stats = scanStats;
            boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty();
            scanStats.recordScanStart(
                    piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId);
        }

        mScanManager.startScan(scanClient);
    }

    void flushPendingBatchResults(int scannerId) {
        if (DBG) {
            Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId);
        }
        mScanManager.flushBatchScanResults(new ScanClient(scannerId));
    }

    void stopScan(int scannerId) {
        enforceAdminPermission();
        int scanQueueSize =
                mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size();
        if (DBG) {
            Log.d(TAG, "stopScan() - queue size =" + scanQueueSize);
        }

        AppScanStats app = null;
        app = mScannerMap.getAppScanStatsById(scannerId);
        if (app != null) {
            app.recordScanStop(scannerId);
        }

        mScanManager.stopScan(scannerId);
    }

    void stopScan(PendingIntent intent, String callingPackage) {
        enforceAdminPermission();
        PendingIntentInfo pii = new PendingIntentInfo();
        pii.intent = intent;
        ScannerMap.App app = mScannerMap.getByContextInfo(pii);
        if (VDBG) {
            Log.d(TAG, "stopScan(PendingIntent): app found = " + app);
        }
        if (app != null) {
            final int scannerId = app.id;
            stopScan(scannerId);
            // Also unregister the scanner
            unregisterScanner(scannerId);
        }
    }

    void disconnectAll() {
        if (DBG) {
            Log.d(TAG, "disconnectAll()");
        }
        Map<Integer, String> connMap = mClientMap.getConnectedMap();
        for (Map.Entry<Integer, String> entry : connMap.entrySet()) {
            if (DBG) {
                Log.d(TAG, "disconnecting addr:" + entry.getValue());
            }
            clientDisconnect(entry.getKey(), entry.getValue());
            //clientDisconnect(int clientIf, String address)
        }
    }

    void unregAll() {
        for (Integer appId : mClientMap.getAllAppsIds()) {
            if (DBG) {
                Log.d(TAG, "unreg:" + appId);
            }
            unregisterClient(appId);
        }
    }

    /**************************************************************************
     * PERIODIC SCANNING
     *************************************************************************/
    void registerSync(ScanResult scanResult, int skip, int timeout,
            IPeriodicAdvertisingCallback callback) {
        enforceAdminPermission();
        mPeriodicScanManager.startSync(scanResult, skip, timeout, callback);
    }

    void unregisterSync(IPeriodicAdvertisingCallback callback) {
        enforceAdminPermission();
        mPeriodicScanManager.stopSync(callback);
    }

    /**************************************************************************
     * ADVERTISING SET
     *************************************************************************/
    void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData,
            AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters,
            AdvertiseData periodicData, int duration, int maxExtAdvEvents,
            IAdvertisingSetCallback callback) {
        enforceAdminPermission();
        mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse,
                periodicParameters, periodicData, duration, maxExtAdvEvents, callback);
    }

    void stopAdvertisingSet(IAdvertisingSetCallback callback) {
        enforceAdminPermission();
        mAdvertiseManager.stopAdvertisingSet(callback);
    }

    void getOwnAddress(int advertiserId) {
        enforcePrivilegedPermission();
        mAdvertiseManager.getOwnAddress(advertiserId);
    }

    void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) {
        enforceAdminPermission();
        mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);
    }

    void setAdvertisingData(int advertiserId, AdvertiseData data) {
        enforceAdminPermission();
        mAdvertiseManager.setAdvertisingData(advertiserId, data);
    }

    void setScanResponseData(int advertiserId, AdvertiseData data) {
        enforceAdminPermission();
        mAdvertiseManager.setScanResponseData(advertiserId, data);
    }

    void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) {
        enforceAdminPermission();
        mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters);
    }

    void setPeriodicAdvertisingParameters(int advertiserId,
            PeriodicAdvertisingParameters parameters) {
        enforceAdminPermission();
        mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters);
    }

    void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
        enforceAdminPermission();
        mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data);
    }

    void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
        enforceAdminPermission();
        mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable);
    }

    /**************************************************************************
     * GATT Service functions - CLIENT
     *************************************************************************/

    void registerClient(UUID uuid, IBluetoothGattCallback callback, boolean eatt_support) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "registerClient() - UUID=" + uuid);
        }
        mClientMap.add(uuid, null, callback, null, this);
        gattClientRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support);
    }

    void unregisterClient(int clientIf) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "unregisterClient() - clientIf=" + clientIf);
        }
        mClientMap.remove(clientIf);
        gattClientUnregisterAppNative(clientIf);
    }

    void clientConnect(int clientIf, String address, boolean isDirect, int transport,
            boolean opportunistic, int phy) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect
                    + ", opportunistic=" + opportunistic + ", phy=" + phy);
        }
        gattClientConnectNative(clientIf, address, isDirect, transport, opportunistic, phy);
    }

    void clientDisconnect(int clientIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (DBG) {
            Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId);
        }

        gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0);
    }

    void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            if (DBG) {
                Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address);
            }
            return;
        }

        if (DBG) {
            Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId);
        }
        gattClientSetPreferredPhyNative(clientIf, address, txPhy, rxPhy, phyOptions);
    }

    void clientReadPhy(int clientIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            if (DBG) {
                Log.d(TAG, "clientReadPhy() - no connection to " + address);
            }
            return;
        }

        if (DBG) {
            Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId);
        }
        gattClientReadPhyNative(clientIf, address);
    }

    int numHwTrackFiltersAvailable() {
        return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements()
                - mScanManager.getCurrentUsedTrackingAdvertisement());
    }

    synchronized List<ParcelUuid> getRegisteredServiceUuids() {
        Utils.enforceAdminPermission(this);
        List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
        for (HandleMap.Entry entry : mHandleMap.mEntries) {
            serviceUuids.add(new ParcelUuid(entry.uuid));
        }
        return serviceUuids;
    }

    List<String> getConnectedDevices() {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Set<String> connectedDevAddress = new HashSet<String>();
        connectedDevAddress.addAll(mClientMap.getConnectedDevices());
        connectedDevAddress.addAll(mServerMap.getConnectedDevices());
        List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress);
        return connectedDeviceList;
    }

    void refreshDevice(int clientIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "refreshDevice() - address=" + address);
        }
        gattClientRefreshNative(clientIf, address);
    }

    void discoverServices(int clientIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (DBG) {
            Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId);
        }

        if (connId != null) {
            gattClientSearchServiceNative(connId, true, 0, 0);
        } else {
            Log.e(TAG, "discoverServices() - No connection for " + address + "...");
        }
    }

    void discoverServiceByUuid(int clientIf, String address, UUID uuid) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId != null) {
            gattClientDiscoverServiceByUuidNative(connId, uuid.getLeastSignificantBits(),
                    uuid.getMostSignificantBits());
        } else {
            Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "...");
        }
    }

    void readCharacteristic(int clientIf, String address, int handle, int authReq) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (VDBG) {
            Log.d(TAG, "readCharacteristic() - address=" + address);
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "readCharacteristic() - No connection for " + address + "...");
            return;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "readCharacteristic() - permission check failed!");
            return;
        }

        gattClientReadCharacteristicNative(connId, handle, authReq);
    }

    void readUsingCharacteristicUuid(int clientIf, String address, UUID uuid, int startHandle,
            int endHandle, int authReq) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (VDBG) {
            Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address);
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "...");
            return;
        }

        if (!permissionCheck(uuid)) {
            Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!");
            return;
        }

        gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(),
                uuid.getMostSignificantBits(), startHandle, endHandle, authReq);
    }

    void writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq,
            byte[] value) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (VDBG) {
            Log.d(TAG, "writeCharacteristic() - address=" + address);
        }

        if (mReliableQueue.contains(address)) {
            writeType = 3; // Prepared write
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
            return;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "writeCharacteristic() - permission check failed!");
            return;
        }

        gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
    }

    void readDescriptor(int clientIf, String address, int handle, int authReq) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (VDBG) {
            Log.d(TAG, "readDescriptor() - address=" + address);
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "readDescriptor() - No connection for " + address + "...");
            return;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "readDescriptor() - permission check failed!");
            return;
        }

        gattClientReadDescriptorNative(connId, handle, authReq);
    }

    ;

    void writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (VDBG) {
            Log.d(TAG, "writeDescriptor() - address=" + address);
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
            return;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "writeDescriptor() - permission check failed!");
            return;
        }

        gattClientWriteDescriptorNative(connId, handle, authReq, value);
    }

    void beginReliableWrite(int clientIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "beginReliableWrite() - address=" + address);
        }
        mReliableQueue.add(address);
    }

    void endReliableWrite(int clientIf, String address, boolean execute) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "endReliableWrite() - address=" + address + " execute: " + execute);
        }
        mReliableQueue.remove(address);

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId != null) {
            gattClientExecuteWriteNative(connId, execute);
        }
    }

    void registerForNotification(int clientIf, String address, int handle, boolean enable) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
        }

        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "registerForNotification() - No connection for " + address + "...");
            return;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "registerForNotification() - permission check failed!");
            return;
        }

        gattClientRegisterForNotificationsNative(clientIf, address, handle, enable);
    }

    void readRemoteRssi(int clientIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "readRemoteRssi() - address=" + address);
        }
        gattClientReadRemoteRssiNative(clientIf, address);
    }

    void configureMTU(int clientIf, String address, int mtu) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu);
        }
        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId != null) {
            gattClientConfigureMTUNative(connId, mtu);
        } else {
            Log.e(TAG, "configureMTU() - No connection for " + address + "...");
        }
    }

    void connectionParameterUpdate(int clientIf, String address, int connectionPriority) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        int minInterval;
        int maxInterval;

        // Peripheral latency
        int latency;

        // Link supervision timeout is measured in N * 10ms
        int timeout = 500; // 5s

        switch (connectionPriority) {
            case BluetoothGatt.CONNECTION_PRIORITY_HIGH:
                minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval);
                maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval);
                latency = getResources().getInteger(R.integer.gatt_high_priority_latency);
                break;

            case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER:
                minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval);
                maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval);
                latency = getResources().getInteger(R.integer.gatt_low_power_latency);
                break;

            default:
                // Using the values for CONNECTION_PRIORITY_BALANCED.
                minInterval =
                        getResources().getInteger(R.integer.gatt_balanced_priority_min_interval);
                maxInterval =
                        getResources().getInteger(R.integer.gatt_balanced_priority_max_interval);
                latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency);
                break;
        }

        if (DBG) {
            Log.d(TAG, "connectionParameterUpdate() - address=" + address + "params="
                    + connectionPriority + " interval=" + minInterval + "/" + maxInterval);
        }
        gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, latency,
                timeout, 0, 0);
    }

    void leConnectionUpdate(int clientIf, String address, int minInterval,
                            int maxInterval, int peripheralLatency,
                            int supervisionTimeout, int minConnectionEventLen,
                            int maxConnectionEventLen) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "leConnectionUpdate() - address=" + address + ", intervals="
                        + minInterval + "/" + maxInterval + ", latency=" + peripheralLatency
                        + ", timeout=" + supervisionTimeout + "msec" + ", min_ce="
                        + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen);


        }
        gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval,
                                            peripheralLatency, supervisionTimeout,
                                            minConnectionEventLen, maxConnectionEventLen);
    }

    /**************************************************************************
     * Callback functions - SERVER
     *************************************************************************/

    void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)
            throws RemoteException {

        UUID uuid = new UUID(uuidMsb, uuidLsb);
        if (DBG) {
            Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf);
        }
        ServerMap.App app = mServerMap.getByUuid(uuid);
        if (app != null) {
            app.id = serverIf;
            app.linkToDeath(new ServerDeathRecipient(serverIf));
            app.callback.onServerRegistered(status, serverIf);
        }
    }

    void onServiceAdded(int status, int serverIf, List<GattDbElement> service)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServiceAdded(), status=" + status);
        }

        if (status != 0) {
            return;
        }

        GattDbElement svcEl = service.get(0);
        int srvcHandle = svcEl.attributeHandle;

        BluetoothGattService svc = null;

        for (GattDbElement el : service) {
            if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) {
                mHandleMap.addService(serverIf, el.attributeHandle, el.uuid,
                        BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false);
                svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle,
                        BluetoothGattService.SERVICE_TYPE_PRIMARY);
            } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) {
                mHandleMap.addService(serverIf, el.attributeHandle, el.uuid,
                        BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false);
                svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle,
                        BluetoothGattService.SERVICE_TYPE_SECONDARY);
            } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) {
                mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle);
                svc.addCharacteristic(
                        new BluetoothGattCharacteristic(el.uuid, el.attributeHandle, el.properties,
                                el.permissions));
            } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) {
                mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle);
                List<BluetoothGattCharacteristic> chars = svc.getCharacteristics();
                chars.get(chars.size() - 1)
                        .addDescriptor(new BluetoothGattDescriptor(el.uuid, el.attributeHandle,
                                el.permissions));
            }
        }
        mHandleMap.setStarted(serverIf, srvcHandle, true);

        ServerMap.App app = mServerMap.getById(serverIf);
        if (app != null) {
            app.callback.onServiceAdded(status, svc);
        }
    }

    void onServiceStopped(int status, int serverIf, int srvcHandle) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle + ", status=" + status);
        }
        if (status == 0) {
            mHandleMap.setStarted(serverIf, srvcHandle, false);
        }
        stopNextService(serverIf, status);
    }

    void onServiceDeleted(int status, int serverIf, int srvcHandle) {
        if (DBG) {
            Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle + ", status=" + status);
        }
        mHandleMap.deleteService(serverIf, srvcHandle);
    }

    void onClientConnected(String address, boolean connected, int connId, int serverIf)
            throws RemoteException {

        if (DBG) {
            Log.d(TAG,
                    "onClientConnected() connId=" + connId + ", address=" + address + ", connected="
                            + connected);
        }

        ServerMap.App app = mServerMap.getById(serverIf);
        if (app == null) {
            return;
        }

        if (connected) {
            mServerMap.addConnection(serverIf, connId, address);
        } else {
            mServerMap.removeConnection(serverIf, connId);
        }

        app.callback.onServerConnectionState((byte) 0, serverIf, connected, address);
    }

    void onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset,
            boolean isLong) throws RemoteException {
        if (VDBG) {
            Log.d(TAG, "onServerReadCharacteristic() connId=" + connId + ", address=" + address
                    + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset);
        }

        HandleMap.Entry entry = mHandleMap.getByHandle(handle);
        if (entry == null) {
            return;
        }

        mHandleMap.addRequest(transId, handle);

        ServerMap.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
            return;
        }

        app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle);
    }

    void onServerReadDescriptor(String address, int connId, int transId, int handle, int offset,
            boolean isLong) throws RemoteException {
        if (VDBG) {
            Log.d(TAG, "onServerReadDescriptor() connId=" + connId + ", address=" + address
                    + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset);
        }

        HandleMap.Entry entry = mHandleMap.getByHandle(handle);
        if (entry == null) {
            return;
        }

        mHandleMap.addRequest(transId, handle);

        ServerMap.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
            return;
        }

        app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle);
    }

    void onServerWriteCharacteristic(String address, int connId, int transId, int handle,
            int offset, int length, boolean needRsp, boolean isPrep, byte[] data)
            throws RemoteException {
        if (VDBG) {
            Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId + ", address=" + address
                    + ", handle=" + handle + ", requestId=" + transId + ", isPrep=" + isPrep
                    + ", offset=" + offset);
        }

        HandleMap.Entry entry = mHandleMap.getByHandle(handle);
        if (entry == null) {
            return;
        }

        mHandleMap.addRequest(transId, handle);

        ServerMap.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
            return;
        }

        app.callback.onCharacteristicWriteRequest(address, transId, offset, length, isPrep, needRsp,
                handle, data);
    }

    void onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset,
            int length, boolean needRsp, boolean isPrep, byte[] data) throws RemoteException {
        if (VDBG) {
            Log.d(TAG, "onAttributeWrite() connId=" + connId + ", address=" + address + ", handle="
                    + handle + ", requestId=" + transId + ", isPrep=" + isPrep + ", offset="
                    + offset);
        }

        HandleMap.Entry entry = mHandleMap.getByHandle(handle);
        if (entry == null) {
            return;
        }

        mHandleMap.addRequest(transId, handle);

        ServerMap.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
            return;
        }

        app.callback.onDescriptorWriteRequest(address, transId, offset, length, isPrep, needRsp,
                handle, data);
    }

    void onExecuteWrite(String address, int connId, int transId, int execWrite)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onExecuteWrite() connId=" + connId + ", address=" + address + ", transId="
                    + transId);
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onExecuteWrite(address, transId, execWrite == 1);
    }

    void onResponseSendCompleted(int status, int attrHandle) {
        if (DBG) {
            Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle);
        }
    }

    void onNotificationSent(int connId, int status) throws RemoteException {
        if (VDBG) {
            Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
        }

        String address = mServerMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        if (!app.isCongested) {
            app.callback.onNotificationSent(address, status);
        } else {
            if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                status = BluetoothGatt.GATT_SUCCESS;
            }
            app.queueCallback(new CallbackInfo(address, status));
        }
    }

    void onServerCongestion(int connId, boolean congested) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested);
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.isCongested = congested;
        while (!app.isCongested) {
            CallbackInfo callbackInfo = app.popQueuedCallback();
            if (callbackInfo == null) {
                return;
            }
            app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status);
        }
    }

    void onMtuChanged(int connId, int mtu) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu);
        }

        String address = mServerMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onMtuChanged(address, mtu);
    }

    /**************************************************************************
     * GATT Service functions - SERVER
     *************************************************************************/

    void registerServer(UUID uuid, IBluetoothGattServerCallback callback, boolean eatt_support) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "registerServer() - UUID=" + uuid);
        }
        mServerMap.add(uuid, null, callback, null, this);
        gattServerRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support);
    }

    void unregisterServer(int serverIf) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "unregisterServer() - serverIf=" + serverIf);
        }

        deleteServices(serverIf);

        mServerMap.remove(serverIf);
        gattServerUnregisterAppNative(serverIf);
    }

    void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "serverConnect() - address=" + address);
        }
        gattServerConnectNative(serverIf, address, isDirect, transport);
    }

    void serverDisconnect(int serverIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
        if (DBG) {
            Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId);
        }

        gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0);
    }

    void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
        if (connId == null) {
            if (DBG) {
                Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address);
            }
            return;
        }

        if (DBG) {
            Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId);
        }
        gattServerSetPreferredPhyNative(serverIf, address, txPhy, rxPhy, phyOptions);
    }

    void serverReadPhy(int serverIf, String address) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
        if (connId == null) {
            if (DBG) {
                Log.d(TAG, "serverReadPhy() - no connection to " + address);
            }
            return;
        }

        if (DBG) {
            Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId);
        }
        gattServerReadPhyNative(serverIf, address);
    }

    void addService(int serverIf, BluetoothGattService service) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "addService() - uuid=" + service.getUuid());
        }

        List<GattDbElement> db = new ArrayList<GattDbElement>();

        if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) {
            db.add(GattDbElement.createPrimaryService(service.getUuid()));
        } else {
            db.add(GattDbElement.createSecondaryService(service.getUuid()));
        }

        for (BluetoothGattService includedService : service.getIncludedServices()) {
            int inclSrvcHandle = includedService.getInstanceId();

            if (mHandleMap.checkServiceExists(includedService.getUuid(), inclSrvcHandle)) {
                db.add(GattDbElement.createIncludedService(inclSrvcHandle));
            } else {
                Log.e(TAG,
                        "included service with UUID " + includedService.getUuid() + " not found!");
            }
        }

        for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
            int permission =
                    ((characteristic.getKeySize() - 7) << 12) + characteristic.getPermissions();
            db.add(GattDbElement.createCharacteristic(characteristic.getUuid(),
                    characteristic.getProperties(), permission));

            for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
                permission =
                        ((characteristic.getKeySize() - 7) << 12) + descriptor.getPermissions();
                db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission));
            }
        }

        gattServerAddServiceNative(serverIf, db);
    }

    void removeService(int serverIf, int handle) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "removeService() - handle=" + handle);
        }

        gattServerDeleteServiceNative(serverIf, handle);
    }

    void clearServices(int serverIf) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) {
            Log.d(TAG, "clearServices()");
        }
        deleteServices(serverIf);
    }

    void sendResponse(int serverIf, String address, int requestId, int status, int offset,
            byte[] value) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (VDBG) {
            Log.d(TAG, "sendResponse() - address=" + address);
        }

        int handle = 0;
        HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
        if (entry != null) {
            handle = entry.handle;
        }

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
        gattServerSendResponseNative(serverIf, connId != null ? connId : 0, requestId,
                (byte) status, handle, offset, value, (byte) 0);
        mHandleMap.deleteRequest(requestId);
    }

    void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (VDBG) {
            Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle);
        }

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
        if (connId == null || connId == 0) {
            return;
        }

        if (confirm) {
            gattServerSendIndicationNative(serverIf, handle, connId, value);
        } else {
            gattServerSendNotificationNative(serverIf, handle, connId, value);
        }
    }


    /**************************************************************************
     * Private functions
     *************************************************************************/

    private boolean isHidSrvcUuid(final UUID uuid) {
        return HID_SERVICE_UUID.equals(uuid);
    }

    private boolean isHidCharUuid(final UUID uuid) {
        for (UUID hidUuid : HID_UUIDS) {
            if (hidUuid.equals(uuid)) {
                return true;
            }
        }
        return false;
    }

    private boolean isAndroidTvRemoteSrvcUuid(final UUID uuid) {
        return ANDROID_TV_REMOTE_SERVICE_UUID.equals(uuid);
    }

    private boolean isFidoSrvcUuid(final UUID uuid) {
        return FIDO_SERVICE_UUID.equals(uuid);
    }

    private int getDeviceType(BluetoothDevice device) {
        int type = gattClientGetDeviceTypeNative(device.getAddress());
        if (DBG) {
            Log.d(TAG, "getDeviceType() - device=" + device + ", type=" + type);
        }
        return type;
    }

    private void enforceAdminPermission() {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
    }

    private boolean needsPrivilegedPermissionForScan(ScanSettings settings) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        // BLE scan only mode needs special permission.
        if (adapter.getState() != BluetoothAdapter.STATE_ON) {
            return true;
        }

        // Regular scan, no special permission.
        if (settings == null) {
            return false;
        }

        // Regular scan, no special permission.
        if (settings.getReportDelayMillis() == 0) {
            return false;
        }

        // Batch scan, truncated mode needs permission.
        return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED;
    }

    // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be
    // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission.
    private void enforcePrivilegedPermission() {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
    }

    // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other
    // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does
    // not have UPDATE_DEVICE_STATS permission.
    private void enforceImpersonatationPermission() {
        enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
                "Need UPDATE_DEVICE_STATS permission");
    }

    private void stopNextService(int serverIf, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "stopNextService() - serverIf=" + serverIf + ", status=" + status);
        }

        if (status == 0) {
            List<HandleMap.Entry> entries = mHandleMap.getEntries();
            for (HandleMap.Entry entry : entries) {
                if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf
                        || !entry.started) {
                    continue;
                }

                gattServerStopServiceNative(serverIf, entry.handle);
                return;
            }
        }
    }

    private void deleteServices(int serverIf) {
        if (DBG) {
            Log.d(TAG, "deleteServices() - serverIf=" + serverIf);
        }

        /*
         * Figure out which handles to delete.
         * The handles are copied into a new list to avoid race conditions.
         */
        List<Integer> handleList = new ArrayList<Integer>();
        List<HandleMap.Entry> entries = mHandleMap.getEntries();
        for (HandleMap.Entry entry : entries) {
            if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf) {
                continue;
            }
            handleList.add(entry.handle);
        }

        /* Now actually delete the services.... */
        for (Integer handle : handleList) {
            gattServerDeleteServiceNative(serverIf, handle);
        }
    }

    @VisibleForTesting
    List<UUID> parseUuids(byte[] advData) {
        List<UUID> uuids = new ArrayList<UUID>();

        int offset = 0;
        while (offset < (advData.length - 2)) {
            int len = Byte.toUnsignedInt(advData[offset++]);
            if (len == 0) {
                break;
            }

            int type = advData[offset++];
            switch (type) {
                case 0x02: // Partial list of 16-bit UUIDs
                case 0x03: // Complete list of 16-bit UUIDs
                    while (len > 1) {
                        int uuid16 = advData[offset++];
                        uuid16 += (advData[offset++] << 8);
                        len -= 2;
                        String uuid_prefix = Integer.toHexString(uuid16);
                        // Pad zeroes to make uuid_prefix length exactly 8.
                        uuids.add(UUID.fromString(UUID_ZERO_PAD.substring(uuid_prefix.length())
                                                  + uuid_prefix + UUID_SUFFIX));
                    }
                    break;

                default:
                    offset += (len - 1);
                    break;
            }
        }

        return uuids;
    }

    void dumpRegisterId(StringBuilder sb) {
        sb.append("  Scanner:\n");
        for (Integer appId : mScannerMap.getAllAppsIds()) {
            println(sb, "    app_if: " + appId + ", appName: " + mScannerMap.getById(appId).name);
        }
        sb.append("  Client:\n");
        for (Integer appId : mClientMap.getAllAppsIds()) {
            println(sb, "    app_if: " + appId + ", appName: " + mClientMap.getById(appId).name);
        }
        sb.append("  Server:\n");
        for (Integer appId : mServerMap.getAllAppsIds()) {
            println(sb, "    app_if: " + appId + ", appName: " + mServerMap.getById(appId).name);
        }
        sb.append("\n\n");
    }

    @Override
    public void dump(StringBuilder sb) {
        super.dump(sb);
        println(sb, "mAdvertisingServiceUuids:");
        for (UUID uuid : mAdvertisingServiceUuids) {
            println(sb, "  " + uuid);
        }

        println(sb, "mMaxScanFilters: " + mMaxScanFilters);

        sb.append("\nRegistered App\n");
        dumpRegisterId(sb);

        sb.append("GATT Scanner Map\n");
        mScannerMap.dump(sb);

        sb.append("GATT Client Map\n");
        mClientMap.dump(sb);

        sb.append("GATT Server Map\n");
        mServerMap.dump(sb);

        sb.append("GATT Handle Map\n");
        mHandleMap.dump(sb);
    }

    void addScanEvent(BluetoothMetricsProto.ScanEvent event) {
        synchronized (mScanEvents) {
            if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) {
                mScanEvents.remove();
            }
            mScanEvents.add(event);
        }
    }

    @Override
    public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) {
        synchronized (mScanEvents) {
            builder.addAllScanEvent(mScanEvents);
        }
    }

    /**************************************************************************
     * GATT Test functions
     *************************************************************************/

    void gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4,
            int p5) {
        if (bda1 == null) {
            bda1 = "00:00:00:00:00:00";
        }
        if (uuid1 != null) {
            gattTestNative(command, uuid1.getLeastSignificantBits(), uuid1.getMostSignificantBits(),
                    bda1, p1, p2, p3, p4, p5);
        } else {
            gattTestNative(command, 0, 0, bda1, p1, p2, p3, p4, p5);
        }
    }

    private native void gattTestNative(int command, long uuid1Lsb, long uuid1Msb, String bda1,
            int p1, int p2, int p3, int p4, int p5);

    /**************************************************************************
     * Native functions prototypes
     *************************************************************************/

    private static native void classInitNative();

    private native void initializeNative();

    private native void cleanupNative();

    private native int gattClientGetDeviceTypeNative(String address);

    private native void gattClientRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support);

    private native void gattClientUnregisterAppNative(int clientIf);

    private native void gattClientConnectNative(int clientIf, String address, boolean isDirect,
            int transport, boolean opportunistic, int initiatingPhys);

    private native void gattClientDisconnectNative(int clientIf, String address, int connId);

    private native void gattClientSetPreferredPhyNative(int clientIf, String address, int txPhy,
            int rxPhy, int phyOptions);

    private native void gattClientReadPhyNative(int clientIf, String address);

    private native void gattClientRefreshNative(int clientIf, String address);

    private native void gattClientSearchServiceNative(int connId, boolean searchAll,
            long serviceUuidLsb, long serviceUuidMsb);

    private native void gattClientDiscoverServiceByUuidNative(int connId, long serviceUuidLsb,
            long serviceUuidMsb);

    private native void gattClientGetGattDbNative(int connId);

    private native void gattClientReadCharacteristicNative(int connId, int handle, int authReq);

    private native void gattClientReadUsingCharacteristicUuidNative(int connId, long uuidMsb,
            long uuidLsb, int sHandle, int eHandle, int authReq);

    private native void gattClientReadDescriptorNative(int connId, int handle, int authReq);

    private native void gattClientWriteCharacteristicNative(int connId, int handle, int writeType,
            int authReq, byte[] value);

    private native void gattClientWriteDescriptorNative(int connId, int handle, int authReq,
            byte[] value);

    private native void gattClientExecuteWriteNative(int connId, boolean execute);

    private native void gattClientRegisterForNotificationsNative(int clientIf, String address,
            int handle, boolean enable);

    private native void gattClientReadRemoteRssiNative(int clientIf, String address);

    private native void gattClientConfigureMTUNative(int connId, int mtu);

    private native void gattConnectionParameterUpdateNative(int clientIf, String address,
            int minInterval, int maxInterval, int latency, int timeout, int minConnectionEventLen,
            int maxConnectionEventLen);

    private native void gattServerRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support);

    private native void gattServerUnregisterAppNative(int serverIf);

    private native void gattServerConnectNative(int serverIf, String address, boolean isDirect,
            int transport);

    private native void gattServerDisconnectNative(int serverIf, String address, int connId);

    private native void gattServerSetPreferredPhyNative(int clientIf, String address, int txPhy,
            int rxPhy, int phyOptions);

    private native void gattServerReadPhyNative(int clientIf, String address);

    private native void gattServerAddServiceNative(int serverIf, List<GattDbElement> service);

    private native void gattServerStopServiceNative(int serverIf, int svcHandle);

    private native void gattServerDeleteServiceNative(int serverIf, int svcHandle);

    private native void gattServerSendIndicationNative(int serverIf, int attrHandle, int connId,
            byte[] val);

    private native void gattServerSendNotificationNative(int serverIf, int attrHandle, int connId,
            byte[] val);

    private native void gattServerSendResponseNative(int serverIf, int connId, int transId,
            int status, int handle, int offset, byte[] val, int authReq);
}
