AdapterService.java revision 75b64427d7ba22d0f1ca3049eb6dd4686f5f57c5
15e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux/*
25e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * Copyright (C) 2012 The Android Open Source Project
35e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux *
45e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * Licensed under the Apache License, Version 2.0 (the "License");
55e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * you may not use this file except in compliance with the License.
65e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * You may obtain a copy of the License at
75e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux *
85e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux *      http://www.apache.org/licenses/LICENSE-2.0
95e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux *
105e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * Unless required by applicable law or agreed to in writing, software
115e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * distributed under the License is distributed on an "AS IS" BASIS,
125e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * See the License for the specific language governing permissions and
145e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux * limitations under the License.
155e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux */
165e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
175e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuxpackage com.android.bluetooth.btservice;
185e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
19ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieuximport android.app.ActivityManager;
205e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.app.AlarmManager;
215e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.app.PendingIntent;
225e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.app.Service;
234e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.bluetooth.BluetoothActivityEnergyInfo;
245e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.BluetoothAdapter;
255e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.BluetoothClass;
265e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.BluetoothDevice;
275e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.BluetoothProfile;
285e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.IBluetooth;
295e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.IBluetoothCallback;
305e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.IBluetoothSocketManager;
315e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.OobData;
325e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.bluetooth.UidTraffic;
335e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.content.BroadcastReceiver;
345e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.content.Context;
35ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieuximport android.content.Intent;
36ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieuximport android.content.IntentFilter;
375e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.content.SharedPreferences;
385e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.content.pm.PackageManager;
395e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.os.AsyncTask;
404e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.BatteryStats;
414e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.Binder;
424e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.Bundle;
434e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.Handler;
444e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.IBinder;
454e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.Looper;
465e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.os.Message;
475e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.os.ParcelUuid;
485e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.os.PowerManager;
49ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieuximport android.os.Process;
50ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieuximport android.os.RemoteCallbackList;
514e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.RemoteException;
525e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.os.ResultReceiver;
535e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.os.ServiceManager;
544e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.SystemClock;
554e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.UserHandle;
564e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.os.UserManager;
574e7ee09e878178873241846757b178535da3dd76James Lemieuximport android.provider.Settings;
585e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.text.TextUtils;
595e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.util.Base64;
605e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.util.Log;
615e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.util.Slog;
625e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport android.util.SparseArray;
635e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
645e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.bluetooth.Utils;
655e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
665e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.bluetooth.gatt.GattService;
675e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.bluetooth.sdp.SdpManager;
685e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.internal.R;
695e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.internal.annotations.VisibleForTesting;
705e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.android.internal.app.IBatteryStats;
715e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
725e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport com.google.protobuf.micro.InvalidProtocolBufferMicroException;
735e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
745e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport java.io.FileDescriptor;
755e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport java.io.FileOutputStream;
765e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport java.io.IOException;
775e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport java.io.PrintWriter;
785e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport java.util.ArrayList;
795e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuximport java.util.Arrays;
80a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieuximport java.util.HashMap;
81a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux
825e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieuxpublic class AdapterService extends Service {
83a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private static final String TAG = "BluetoothAdapterService";
84a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private static final boolean DBG = true;
855e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private static final boolean VERBOSE = false;
865e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
875e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private static final int MIN_OFFLOADED_FILTERS = 10;
88a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024;
89a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux
905e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private final Object mEnergyInfoLock = new Object();
91a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private int mStackReportedState;
92a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private long mTxTimeTotalMs;
93a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private long mRxTimeTotalMs;
94a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private long mIdleTimeTotalMs;
95a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private long mEnergyUsedTotalVoltAmpSecMicro;
96a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>();
97a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux
98a0a870f57847639d3e28ea72ba7a6f45c1e1af90James Lemieux    private final ArrayList<ProfileService> mRegisteredProfiles = new ArrayList<>();
995e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private final ArrayList<ProfileService> mRunningProfiles = new ArrayList<>();
1005e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
1015e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    public static final String ACTION_LOAD_ADAPTER_PROPERTIES =
1025e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux            "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES";
1035e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    public static final String ACTION_SERVICE_STATE_CHANGED =
1045e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux            "com.android.bluetooth.btservice.action.STATE_CHANGED";
1055e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    public static final String EXTRA_ACTION = "action";
106ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux    public static final int PROFILE_CONN_REJECTED = 2;
1075e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
1085e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private static final String ACTION_ALARM_WAKEUP =
1095e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux            "com.android.bluetooth.btservice.action.ALARM_WAKEUP";
1105e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
1115e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    public static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
1125e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    public static final String BLUETOOTH_PRIVILEGED =
1135e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux            android.Manifest.permission.BLUETOOTH_PRIVILEGED;
1145e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
1155e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    static final String LOCAL_MAC_ADDRESS_PERM = android.Manifest.permission.LOCAL_MAC_ADDRESS;
1165e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP;
1175e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
118ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux    private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE =
1195e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux            "phonebook_access_permission";
1204e7ee09e878178873241846757b178535da3dd76James Lemieux    private static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE =
1215e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux            "message_access_permission";
1225e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission";
1235e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
1244e7ee09e878178873241846757b178535da3dd76James Lemieux    private static final String[] DEVICE_TYPE_NAMES = new String[]{
1254e7ee09e878178873241846757b178535da3dd76James Lemieux            "???", "BR/EDR", "LE", "DUAL"
1264e7ee09e878178873241846757b178535da3dd76James Lemieux    };
1274e7ee09e878178873241846757b178535da3dd76James Lemieux
1284e7ee09e878178873241846757b178535da3dd76James Lemieux    private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30;
1294e7ee09e878178873241846757b178535da3dd76James Lemieux
1304e7ee09e878178873241846757b178535da3dd76James Lemieux    static {
1314e7ee09e878178873241846757b178535da3dd76James Lemieux        classInitNative();
1325e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    }
1335e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux
1345e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private static AdapterService sAdapterService;
1354e7ee09e878178873241846757b178535da3dd76James Lemieux
1364e7ee09e878178873241846757b178535da3dd76James Lemieux    public static synchronized AdapterService getAdapterService() {
1374e7ee09e878178873241846757b178535da3dd76James Lemieux        Log.d(TAG, "getAdapterService() - returning " + sAdapterService);
1384e7ee09e878178873241846757b178535da3dd76James Lemieux        return sAdapterService;
1394e7ee09e878178873241846757b178535da3dd76James Lemieux    }
1404e7ee09e878178873241846757b178535da3dd76James Lemieux
1414e7ee09e878178873241846757b178535da3dd76James Lemieux    private static synchronized void setAdapterService(AdapterService instance) {
1424e7ee09e878178873241846757b178535da3dd76James Lemieux        Log.d(TAG, "setAdapterService() - trying to set service to " + instance);
1434e7ee09e878178873241846757b178535da3dd76James Lemieux        if (instance == null) {
1444e7ee09e878178873241846757b178535da3dd76James Lemieux            return;
1454e7ee09e878178873241846757b178535da3dd76James Lemieux        }
1464e7ee09e878178873241846757b178535da3dd76James Lemieux        sAdapterService = instance;
1474e7ee09e878178873241846757b178535da3dd76James Lemieux    }
1484e7ee09e878178873241846757b178535da3dd76James Lemieux
1494e7ee09e878178873241846757b178535da3dd76James Lemieux    private static synchronized void clearAdapterService(AdapterService current) {
1504e7ee09e878178873241846757b178535da3dd76James Lemieux        if (sAdapterService == current) {
1514e7ee09e878178873241846757b178535da3dd76James Lemieux            sAdapterService = null;
1524e7ee09e878178873241846757b178535da3dd76James Lemieux        }
1534e7ee09e878178873241846757b178535da3dd76James Lemieux    }
1544e7ee09e878178873241846757b178535da3dd76James Lemieux
1554e7ee09e878178873241846757b178535da3dd76James Lemieux    private AdapterProperties mAdapterProperties;
1564e7ee09e878178873241846757b178535da3dd76James Lemieux    private AdapterState mAdapterStateMachine;
1574e7ee09e878178873241846757b178535da3dd76James Lemieux    private BondStateMachine mBondStateMachine;
1584e7ee09e878178873241846757b178535da3dd76James Lemieux    private JniCallbacks mJniCallbacks;
1594e7ee09e878178873241846757b178535da3dd76James Lemieux    private RemoteDevices mRemoteDevices;
1604e7ee09e878178873241846757b178535da3dd76James Lemieux
1614e7ee09e878178873241846757b178535da3dd76James Lemieux    /* TODO: Consider to remove the search API from this class, if changed to use call-back */
1624e7ee09e878178873241846757b178535da3dd76James Lemieux    private SdpManager mSdpManager = null;
1634e7ee09e878178873241846757b178535da3dd76James Lemieux
1644e7ee09e878178873241846757b178535da3dd76James Lemieux    private boolean mNativeAvailable;
1654e7ee09e878178873241846757b178535da3dd76James Lemieux    private boolean mCleaningUp;
1664e7ee09e878178873241846757b178535da3dd76James Lemieux    private final HashMap<String, Integer> mProfileServicesState = new HashMap<String, Integer>();
1674e7ee09e878178873241846757b178535da3dd76James Lemieux    //Only BluetoothManagerService should be registered
1684e7ee09e878178873241846757b178535da3dd76James Lemieux    private RemoteCallbackList<IBluetoothCallback> mCallbacks;
1694e7ee09e878178873241846757b178535da3dd76James Lemieux    private int mCurrentRequestId;
1704e7ee09e878178873241846757b178535da3dd76James Lemieux    private boolean mQuietmode = false;
1714e7ee09e878178873241846757b178535da3dd76James Lemieux
1724e7ee09e878178873241846757b178535da3dd76James Lemieux    private AlarmManager mAlarmManager;
1734e7ee09e878178873241846757b178535da3dd76James Lemieux    private PendingIntent mPendingAlarm;
1744e7ee09e878178873241846757b178535da3dd76James Lemieux    private IBatteryStats mBatteryStats;
1754e7ee09e878178873241846757b178535da3dd76James Lemieux    private PowerManager mPowerManager;
1764e7ee09e878178873241846757b178535da3dd76James Lemieux    private PowerManager.WakeLock mWakeLock;
1775e0c5c4846f73565bf07542f64bea8208002f55cJames Lemieux    private String mWakeLockName;
178    private UserManager mUserManager;
179
180    private ProfileObserver mProfileObserver;
181    private PhonePolicy mPhonePolicy;
182    private ActiveDeviceManager mActiveDeviceManager;
183
184    /**
185     * Register a {@link ProfileService} with AdapterService.
186     *
187     * @param profile the service being added.
188     */
189    public void addProfile(ProfileService profile) {
190        Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile);
191        mHandler.sendMessage(m);
192    }
193
194    /**
195     * Unregister a ProfileService with AdapterService.
196     *
197     * @param profile the service being removed.
198     */
199    public void removeProfile(ProfileService profile) {
200        Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile);
201        mHandler.sendMessage(m);
202    }
203
204    /**
205     * Notify AdapterService that a ProfileService has started or stopped.
206     *
207     * @param profile the service being removed.
208     * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF}
209     */
210    public void onProfileServiceStateChanged(ProfileService profile, int state) {
211        if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
212            throw new IllegalArgumentException(BluetoothAdapter.nameForState(state));
213        }
214        Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
215        m.obj = profile;
216        m.arg1 = state;
217        mHandler.sendMessage(m);
218    }
219
220    private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1;
221    private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
222    private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;
223
224    class AdapterServiceHandler extends Handler {
225        @Override
226        public void handleMessage(Message msg) {
227            debugLog("handleMessage() - Message: " + msg.what);
228
229            switch (msg.what) {
230                case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:
231                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
232                    processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);
233                    break;
234                case MESSAGE_PROFILE_SERVICE_REGISTERED:
235                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED");
236                    registerProfileService((ProfileService) msg.obj);
237                    break;
238                case MESSAGE_PROFILE_SERVICE_UNREGISTERED:
239                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
240                    unregisterProfileService((ProfileService) msg.obj);
241                    break;
242            }
243        }
244
245        private void registerProfileService(ProfileService profile) {
246            if (mRegisteredProfiles.contains(profile)) {
247                Log.e(TAG, profile.getName() + " already registered.");
248                return;
249            }
250            mRegisteredProfiles.add(profile);
251        }
252
253        private void unregisterProfileService(ProfileService profile) {
254            if (!mRegisteredProfiles.contains(profile)) {
255                Log.e(TAG, profile.getName() + " not registered (UNREGISTERED).");
256                return;
257            }
258            mRegisteredProfiles.remove(profile);
259        }
260
261        private void processProfileServiceStateChanged(ProfileService profile, int state) {
262            switch (state) {
263                case BluetoothAdapter.STATE_ON:
264                    if (!mRegisteredProfiles.contains(profile)) {
265                        Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
266                        return;
267                    }
268                    if (mRunningProfiles.contains(profile)) {
269                        Log.e(TAG, profile.getName() + " already running.");
270                        return;
271                    }
272                    mRunningProfiles.add(profile);
273                    if (GattService.class.getSimpleName().equals(profile.getName())) {
274                        mAdapterStateMachine.sendMessage(
275                                mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));
276                    }
277                    if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
278                            && mRegisteredProfiles.size() == mRunningProfiles.size()) {
279                        mAdapterStateMachine.sendMessage(
280                                mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED));
281                    }
282                    break;
283                case BluetoothAdapter.STATE_OFF:
284                    if (!mRegisteredProfiles.contains(profile)) {
285                        Log.e(TAG, profile.getName() + " not registered (STATE_OFF).");
286                        return;
287                    }
288                    if (!mRunningProfiles.contains(profile)) {
289                        Log.e(TAG, profile.getName() + " not running.");
290                        return;
291                    }
292                    mRunningProfiles.remove(profile);
293                    // If the last profile was removed, or only GATT is left, send BREDR_STOPPED.
294                    if ((mRunningProfiles.size() == 0) || (mRunningProfiles.size() == 1
295                            && (GattService.class.getSimpleName()
296                            .equals(mRunningProfiles.get(0).getName())))) {
297                        mAdapterStateMachine.sendMessage(
298                                mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED));
299                    }
300                    if (mRunningProfiles.size() == 0) {
301                        mAdapterStateMachine.sendMessage(
302                                mAdapterStateMachine.obtainMessage(AdapterState.BLE_STOPPED));
303                    }
304                    break;
305                default:
306                    Log.e(TAG, "Unhandled profile state: " + state);
307            }
308        }
309    }
310
311    private final AdapterServiceHandler mHandler = new AdapterServiceHandler();
312
313    private void updateInteropDatabase() {
314        interopDatabaseClearNative();
315
316        String interopString = Settings.Global.getString(getContentResolver(),
317                Settings.Global.BLUETOOTH_INTEROPERABILITY_LIST);
318        if (interopString == null) {
319            return;
320        }
321        Log.d(TAG, "updateInteropDatabase: [" + interopString + "]");
322
323        String[] entries = interopString.split(";");
324        for (String entry : entries) {
325            String[] tokens = entry.split(",");
326            if (tokens.length != 2) {
327                continue;
328            }
329
330            // Get feature
331            int feature = 0;
332            try {
333                feature = Integer.parseInt(tokens[1]);
334            } catch (NumberFormatException e) {
335                Log.e(TAG, "updateInteropDatabase: Invalid feature '" + tokens[1] + "'");
336                continue;
337            }
338
339            // Get address bytes and length
340            int length = (tokens[0].length() + 1) / 3;
341            if (length < 1 || length > 6) {
342                Log.e(TAG, "updateInteropDatabase: Malformed address string '" + tokens[0] + "'");
343                continue;
344            }
345
346            byte[] addr = new byte[6];
347            int offset = 0;
348            for (int i = 0; i < tokens[0].length(); ) {
349                if (tokens[0].charAt(i) == ':') {
350                    i += 1;
351                } else {
352                    try {
353                        addr[offset++] = (byte) Integer.parseInt(tokens[0].substring(i, i + 2), 16);
354                    } catch (NumberFormatException e) {
355                        offset = 0;
356                        break;
357                    }
358                    i += 2;
359                }
360            }
361
362            // Check if address was parsed ok, otherwise, move on...
363            if (offset == 0) {
364                continue;
365            }
366
367            // Add entry
368            interopDatabaseAddNative(feature, addr, length);
369        }
370    }
371
372    @Override
373    public void onCreate() {
374        super.onCreate();
375        debugLog("onCreate()");
376        mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());
377        mRemoteDevices.init();
378        mBinder = new AdapterServiceBinder(this);
379        mAdapterProperties = new AdapterProperties(this);
380        mAdapterStateMachine = AdapterState.make(this, mAdapterProperties);
381        mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties);
382        initNative();
383        mNativeAvailable = true;
384        mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
385        //Load the name and address
386        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
387        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
388        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE);
389        mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
390        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
391        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
392        mBatteryStats = IBatteryStats.Stub.asInterface(
393                ServiceManager.getService(BatteryStats.SERVICE_NAME));
394
395        mSdpManager = SdpManager.init(this);
396        registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP));
397        mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler());
398        mProfileObserver.start();
399
400        // Phone policy is specific to phone implementations and hence if a device wants to exclude
401        // it out then it can be disabled by using the flag below.
402        if (getResources().getBoolean(com.android.bluetooth.R.bool.enable_phone_policy)) {
403            Log.i(TAG, "Phone policy enabled");
404            mPhonePolicy = new PhonePolicy(this, new ServiceFactory());
405            mPhonePolicy.start();
406        } else {
407            Log.i(TAG, "Phone policy disabled");
408        }
409
410        mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory());
411        mActiveDeviceManager.start();
412
413        setAdapterService(this);
414
415        // First call to getSharedPreferences will result in a file read into
416        // memory cache. Call it here asynchronously to avoid potential ANR
417        // in the future
418        new AsyncTask<Void, Void, Void>() {
419            @Override
420            protected Void doInBackground(Void... params) {
421                getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
422                        Context.MODE_PRIVATE);
423                getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
424                        Context.MODE_PRIVATE);
425                getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
426                return null;
427            }
428        }.execute();
429
430        try {
431            int systemUiUid = getApplicationContext().getPackageManager().getPackageUidAsUser(
432                    "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY,
433                    UserHandle.USER_SYSTEM);
434            Utils.setSystemUiUid(systemUiUid);
435            setSystemUiUidNative(systemUiUid);
436        } catch (PackageManager.NameNotFoundException e) {
437            // Some platforms, such as wearables do not have a system ui.
438            Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
439        }
440
441        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
442        getApplicationContext().registerReceiverAsUser(sUserSwitchedReceiver, UserHandle.ALL,
443                filter, null, null);
444        int fuid = ActivityManager.getCurrentUser();
445        Utils.setForegroundUserId(fuid);
446        setForegroundUserIdNative(fuid);
447    }
448
449    @Override
450    public IBinder onBind(Intent intent) {
451        debugLog("onBind()");
452        return mBinder;
453    }
454
455    @Override
456    public boolean onUnbind(Intent intent) {
457        debugLog("onUnbind() - calling cleanup");
458        cleanup();
459        return super.onUnbind(intent);
460    }
461
462    @Override
463    public void onDestroy() {
464        debugLog("onDestroy()");
465        mProfileObserver.stop();
466        if (!isMock()) {
467            // TODO(b/27859763)
468            Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack");
469            System.exit(0);
470        }
471    }
472
473    public static final BroadcastReceiver sUserSwitchedReceiver = new BroadcastReceiver() {
474        @Override
475        public void onReceive(Context context, Intent intent) {
476            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
477                int fuid = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
478                Utils.setForegroundUserId(fuid);
479                setForegroundUserIdNative(fuid);
480            }
481        }
482    };
483
484    void bleOnProcessStart() {
485        debugLog("bleOnProcessStart()");
486
487        if (getResources().getBoolean(
488                R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
489            Config.init(getApplicationContext());
490        }
491
492        // Reset |mRemoteDevices| whenever BLE is turned off then on
493        // This is to replace the fact that |mRemoteDevices| was
494        // reinitialized in previous code.
495        //
496        // TODO(apanicke): The reason is unclear but
497        // I believe it is to clear the variable every time BLE was
498        // turned off then on. The same effect can be achieved by
499        // calling cleanup but this may not be necessary at all
500        // We should figure out why this is needed later
501        mRemoteDevices.reset();
502        mAdapterProperties.init(mRemoteDevices);
503
504        debugLog("bleOnProcessStart() - Make Bond State Machine");
505        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
506
507        mJniCallbacks.init(mBondStateMachine, mRemoteDevices);
508
509        try {
510            mBatteryStats.noteResetBleScan();
511        } catch (RemoteException e) {
512            Log.w(TAG, "RemoteException trying to send a reset to BatteryStats");
513        }
514
515        //Start Gatt service
516        setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
517    }
518
519    /**
520     * Sets the Bluetooth CoD value of the local adapter if there exists a config value for it.
521     */
522    void setBluetoothClassFromConfig() {
523        int bluetoothClassConfig = retrieveBluetoothClassConfig();
524        if (bluetoothClassConfig != 0) {
525            mAdapterProperties.setBluetoothClass(new BluetoothClass(bluetoothClassConfig));
526        }
527    }
528
529    private int retrieveBluetoothClassConfig() {
530        return Settings.Global.getInt(
531                getContentResolver(), Settings.Global.BLUETOOTH_CLASS_OF_DEVICE, 0);
532    }
533
534    private boolean storeBluetoothClassConfig(int bluetoothClass) {
535        boolean result = Settings.Global.putInt(
536                getContentResolver(), Settings.Global.BLUETOOTH_CLASS_OF_DEVICE, bluetoothClass);
537
538        if (!result) {
539            Log.e(TAG, "Error storing BluetoothClass config - " + bluetoothClass);
540        }
541
542        return result;
543    }
544
545    void startCoreServices() {
546        debugLog("startCoreServices()");
547        Class[] supportedProfileServices = Config.getSupportedProfiles();
548        setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
549    }
550
551    void startBluetoothDisable() {
552        mAdapterStateMachine.sendMessage(
553                mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE));
554    }
555
556    void stopProfileServices() {
557        Class[] supportedProfileServices = Config.getSupportedProfiles();
558        if (mRunningProfiles.size() == 0) {
559            debugLog("stopProfileServices() - No profiles services to stop or already stopped.");
560            return;
561        }
562        setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF);
563    }
564
565    boolean stopGattProfileService() {
566        setProfileServiceState(GattService.class, BluetoothAdapter.STATE_OFF);
567        return true;
568    }
569
570    void updateAdapterState(int prevState, int newState) {
571        if (mCallbacks != null) {
572            int n = mCallbacks.beginBroadcast();
573            debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState(
574                    newState) + " to " + n + " receivers.");
575            for (int i = 0; i < n; i++) {
576                try {
577                    mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);
578                } catch (RemoteException e) {
579                    debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
580                }
581            }
582            mCallbacks.finishBroadcast();
583        }
584    }
585
586    void cleanup() {
587        debugLog("cleanup()");
588        if (mCleaningUp) {
589            errorLog("cleanup() - Service already starting to cleanup, ignoring request...");
590            return;
591        }
592
593        clearAdapterService(this);
594
595        mCleaningUp = true;
596
597        unregisterReceiver(mAlarmBroadcastReceiver);
598
599        if (mPendingAlarm != null) {
600            mAlarmManager.cancel(mPendingAlarm);
601            mPendingAlarm = null;
602        }
603
604        // This wake lock release may also be called concurrently by
605        // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here.
606        synchronized (this) {
607            if (mWakeLock != null) {
608                if (mWakeLock.isHeld()) {
609                    mWakeLock.release();
610                }
611                mWakeLock = null;
612            }
613        }
614
615        if (mAdapterStateMachine != null) {
616            mAdapterStateMachine.doQuit();
617        }
618
619        if (mBondStateMachine != null) {
620            mBondStateMachine.doQuit();
621        }
622
623        if (mRemoteDevices != null) {
624            mRemoteDevices.cleanup();
625        }
626
627        if (mSdpManager != null) {
628            mSdpManager.cleanup();
629            mSdpManager = null;
630        }
631
632        if (mNativeAvailable) {
633            debugLog("cleanup() - Cleaning up adapter native");
634            cleanupNative();
635            mNativeAvailable = false;
636        }
637
638        if (mAdapterProperties != null) {
639            mAdapterProperties.cleanup();
640        }
641
642        if (mJniCallbacks != null) {
643            mJniCallbacks.cleanup();
644        }
645
646        if (mPhonePolicy != null) {
647            mPhonePolicy.cleanup();
648        }
649
650        if (mActiveDeviceManager != null) {
651            mActiveDeviceManager.cleanup();
652        }
653
654        if (mProfileServicesState != null) {
655            mProfileServicesState.clear();
656        }
657
658        if (mBinder != null) {
659            mBinder.cleanup();
660            mBinder = null;  //Do not remove. Otherwise Binder leak!
661        }
662
663        if (mCallbacks != null) {
664            mCallbacks.kill();
665        }
666    }
667
668    private void setProfileServiceState(Class service, int state) {
669        Intent intent = new Intent(this, service);
670        intent.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED);
671        intent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
672        startService(intent);
673    }
674
675    private void setAllProfileServiceStates(Class[] services, int state) {
676        for (Class service : services) {
677            if (GattService.class.getSimpleName().equals(service.getSimpleName())) {
678                continue;
679            }
680            setProfileServiceState(service, state);
681        }
682    }
683
684    private boolean isAvailable() {
685        return !mCleaningUp;
686    }
687
688    /**
689     * Handlers for incoming service calls
690     */
691    private AdapterServiceBinder mBinder;
692
693    /**
694     * The Binder implementation must be declared to be a static class, with
695     * the AdapterService instance passed in the constructor. Furthermore,
696     * when the AdapterService shuts down, the reference to the AdapterService
697     * must be explicitly removed.
698     *
699     * Otherwise, a memory leak can occur from repeated starting/stopping the
700     * service...Please refer to android.os.Binder for further details on
701     * why an inner instance class should be avoided.
702     *
703     */
704    private static class AdapterServiceBinder extends IBluetooth.Stub {
705        private AdapterService mService;
706
707        AdapterServiceBinder(AdapterService svc) {
708            mService = svc;
709        }
710
711        public void cleanup() {
712            mService = null;
713        }
714
715        public AdapterService getService() {
716            if (mService != null && mService.isAvailable()) {
717                return mService;
718            }
719            return null;
720        }
721
722        @Override
723        public boolean isEnabled() {
724            // don't check caller, may be called from system UI
725            AdapterService service = getService();
726            if (service == null) {
727                return false;
728            }
729            return service.isEnabled();
730        }
731
732        @Override
733        public int getState() {
734            // don't check caller, may be called from system UI
735            AdapterService service = getService();
736            if (service == null) {
737                return BluetoothAdapter.STATE_OFF;
738            }
739            return service.getState();
740        }
741
742        @Override
743        public boolean enable() {
744            if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) {
745                Log.w(TAG, "enable() - Not allowed for non-active user and non system user");
746                return false;
747            }
748            AdapterService service = getService();
749            if (service == null) {
750                return false;
751            }
752            return service.enable();
753        }
754
755        @Override
756        public boolean enableNoAutoConnect() {
757            if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) {
758                Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user");
759                return false;
760            }
761
762            AdapterService service = getService();
763            if (service == null) {
764                return false;
765            }
766            return service.enableNoAutoConnect();
767        }
768
769        @Override
770        public boolean disable() {
771            if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) {
772                Log.w(TAG, "disable() - Not allowed for non-active user and non system user");
773                return false;
774            }
775
776            AdapterService service = getService();
777            if (service == null) {
778                return false;
779            }
780            return service.disable();
781        }
782
783        @Override
784        public String getAddress() {
785            if ((Binder.getCallingUid() != Process.SYSTEM_UID)
786                    && (!Utils.checkCallerAllowManagedProfiles(mService))) {
787                Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user");
788                return null;
789            }
790
791            AdapterService service = getService();
792            if (service == null) {
793                return null;
794            }
795            return service.getAddress();
796        }
797
798        @Override
799        public ParcelUuid[] getUuids() {
800            if (!Utils.checkCaller()) {
801                Log.w(TAG, "getUuids() - Not allowed for non-active user");
802                return new ParcelUuid[0];
803            }
804
805            AdapterService service = getService();
806            if (service == null) {
807                return new ParcelUuid[0];
808            }
809            return service.getUuids();
810        }
811
812        @Override
813        public String getName() {
814            if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) {
815                Log.w(TAG, "getName() - Not allowed for non-active user and non system user");
816                return null;
817            }
818
819            AdapterService service = getService();
820            if (service == null) {
821                return null;
822            }
823            return service.getName();
824        }
825
826        @Override
827        public boolean setName(String name) {
828            if (!Utils.checkCaller()) {
829                Log.w(TAG, "setName() - Not allowed for non-active user");
830                return false;
831            }
832
833            AdapterService service = getService();
834            if (service == null) {
835                return false;
836            }
837            return service.setName(name);
838        }
839
840        public BluetoothClass getBluetoothClass() {
841            if (!Utils.checkCaller()) {
842                Log.w(TAG, "getBluetoothClass() - Not allowed for non-active user");
843                return null;
844            }
845
846            AdapterService service = getService();
847            if (service == null) return null;
848            return service.getBluetoothClass();
849        }
850
851        public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
852            if (!Utils.checkCaller()) {
853                Log.w(TAG, "setBluetoothClass() - Not allowed for non-active user");
854                return false;
855            }
856
857            AdapterService service = getService();
858            if (service == null) {
859                return false;
860            }
861            return service.setBluetoothClass(bluetoothClass);
862        }
863
864        @Override
865        public int getScanMode() {
866            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
867                Log.w(TAG, "getScanMode() - Not allowed for non-active user");
868                return BluetoothAdapter.SCAN_MODE_NONE;
869            }
870
871            AdapterService service = getService();
872            if (service == null) {
873                return BluetoothAdapter.SCAN_MODE_NONE;
874            }
875            return service.getScanMode();
876        }
877
878        @Override
879        public boolean setScanMode(int mode, int duration) {
880            if (!Utils.checkCaller()) {
881                Log.w(TAG, "setScanMode() - Not allowed for non-active user");
882                return false;
883            }
884
885            AdapterService service = getService();
886            if (service == null) {
887                return false;
888            }
889            return service.setScanMode(mode, duration);
890        }
891
892        @Override
893        public int getDiscoverableTimeout() {
894            if (!Utils.checkCaller()) {
895                Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user");
896                return 0;
897            }
898
899            AdapterService service = getService();
900            if (service == null) {
901                return 0;
902            }
903            return service.getDiscoverableTimeout();
904        }
905
906        @Override
907        public boolean setDiscoverableTimeout(int timeout) {
908            if (!Utils.checkCaller()) {
909                Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user");
910                return false;
911            }
912
913            AdapterService service = getService();
914            if (service == null) {
915                return false;
916            }
917            return service.setDiscoverableTimeout(timeout);
918        }
919
920        @Override
921        public boolean startDiscovery() {
922            if (!Utils.checkCaller()) {
923                Log.w(TAG, "startDiscovery() - Not allowed for non-active user");
924                return false;
925            }
926
927            AdapterService service = getService();
928            if (service == null) {
929                return false;
930            }
931            return service.startDiscovery();
932        }
933
934        @Override
935        public boolean cancelDiscovery() {
936            if (!Utils.checkCaller()) {
937                Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user");
938                return false;
939            }
940
941            AdapterService service = getService();
942            if (service == null) {
943                return false;
944            }
945            return service.cancelDiscovery();
946        }
947
948        @Override
949        public boolean isDiscovering() {
950            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
951                Log.w(TAG, "isDiscovering() - Not allowed for non-active user");
952                return false;
953            }
954
955            AdapterService service = getService();
956            if (service == null) {
957                return false;
958            }
959            return service.isDiscovering();
960        }
961
962        @Override
963        public long getDiscoveryEndMillis() {
964            if (!Utils.checkCaller()) {
965                Log.w(TAG, "getDiscoveryEndMillis() - Not allowed for non-active user");
966                return -1;
967            }
968
969            AdapterService service = getService();
970            if (service == null) {
971                return -1;
972            }
973            return service.getDiscoveryEndMillis();
974        }
975
976        @Override
977        public BluetoothDevice[] getBondedDevices() {
978            // don't check caller, may be called from system UI
979            AdapterService service = getService();
980            if (service == null) {
981                return new BluetoothDevice[0];
982            }
983            return service.getBondedDevices();
984        }
985
986        @Override
987        public int getAdapterConnectionState() {
988            // don't check caller, may be called from system UI
989            AdapterService service = getService();
990            if (service == null) {
991                return BluetoothAdapter.STATE_DISCONNECTED;
992            }
993            return service.getAdapterConnectionState();
994        }
995
996        @Override
997        public int getProfileConnectionState(int profile) {
998            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
999                Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user");
1000                return BluetoothProfile.STATE_DISCONNECTED;
1001            }
1002
1003            AdapterService service = getService();
1004            if (service == null) {
1005                return BluetoothProfile.STATE_DISCONNECTED;
1006            }
1007            return service.getProfileConnectionState(profile);
1008        }
1009
1010        @Override
1011        public boolean createBond(BluetoothDevice device, int transport) {
1012            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1013                Log.w(TAG, "createBond() - Not allowed for non-active user");
1014                return false;
1015            }
1016
1017            AdapterService service = getService();
1018            if (service == null) {
1019                return false;
1020            }
1021            return service.createBond(device, transport, null);
1022        }
1023
1024        @Override
1025        public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) {
1026            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1027                Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user");
1028                return false;
1029            }
1030
1031            AdapterService service = getService();
1032            if (service == null) {
1033                return false;
1034            }
1035            return service.createBond(device, transport, oobData);
1036        }
1037
1038        @Override
1039        public boolean cancelBondProcess(BluetoothDevice device) {
1040            if (!Utils.checkCaller()) {
1041                Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user");
1042                return false;
1043            }
1044
1045            AdapterService service = getService();
1046            if (service == null) {
1047                return false;
1048            }
1049            return service.cancelBondProcess(device);
1050        }
1051
1052        @Override
1053        public boolean removeBond(BluetoothDevice device) {
1054            if (!Utils.checkCaller()) {
1055                Log.w(TAG, "removeBond() - Not allowed for non-active user");
1056                return false;
1057            }
1058
1059            AdapterService service = getService();
1060            if (service == null) {
1061                return false;
1062            }
1063            return service.removeBond(device);
1064        }
1065
1066        @Override
1067        public int getBondState(BluetoothDevice device) {
1068            // don't check caller, may be called from system UI
1069            AdapterService service = getService();
1070            if (service == null) {
1071                return BluetoothDevice.BOND_NONE;
1072            }
1073            return service.getBondState(device);
1074        }
1075
1076        @Override
1077        public boolean isBondingInitiatedLocally(BluetoothDevice device) {
1078            // don't check caller, may be called from system UI
1079            AdapterService service = getService();
1080            if (service == null) {
1081                return false;
1082            }
1083            return service.isBondingInitiatedLocally(device);
1084        }
1085
1086        @Override
1087        public long getSupportedProfiles() {
1088            AdapterService service = getService();
1089            if (service == null) {
1090                return 0;
1091            }
1092            return service.getSupportedProfiles();
1093        }
1094
1095        @Override
1096        public int getConnectionState(BluetoothDevice device) {
1097            AdapterService service = getService();
1098            if (service == null) {
1099                return 0;
1100            }
1101            return service.getConnectionState(device);
1102        }
1103
1104        @Override
1105        public String getRemoteName(BluetoothDevice device) {
1106            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1107                Log.w(TAG, "getRemoteName() - Not allowed for non-active user");
1108                return null;
1109            }
1110
1111            AdapterService service = getService();
1112            if (service == null) {
1113                return null;
1114            }
1115            return service.getRemoteName(device);
1116        }
1117
1118        @Override
1119        public int getRemoteType(BluetoothDevice device) {
1120            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1121                Log.w(TAG, "getRemoteType() - Not allowed for non-active user");
1122                return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
1123            }
1124
1125            AdapterService service = getService();
1126            if (service == null) {
1127                return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
1128            }
1129            return service.getRemoteType(device);
1130        }
1131
1132        @Override
1133        public String getRemoteAlias(BluetoothDevice device) {
1134            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1135                Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user");
1136                return null;
1137            }
1138
1139            AdapterService service = getService();
1140            if (service == null) {
1141                return null;
1142            }
1143            return service.getRemoteAlias(device);
1144        }
1145
1146        @Override
1147        public boolean setRemoteAlias(BluetoothDevice device, String name) {
1148            if (!Utils.checkCaller()) {
1149                Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user");
1150                return false;
1151            }
1152
1153            AdapterService service = getService();
1154            if (service == null) {
1155                return false;
1156            }
1157            return service.setRemoteAlias(device, name);
1158        }
1159
1160        @Override
1161        public int getRemoteClass(BluetoothDevice device) {
1162            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1163                Log.w(TAG, "getRemoteClass() - Not allowed for non-active user");
1164                return 0;
1165            }
1166
1167            AdapterService service = getService();
1168            if (service == null) {
1169                return 0;
1170            }
1171            return service.getRemoteClass(device);
1172        }
1173
1174        @Override
1175        public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
1176            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1177                Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user");
1178                return new ParcelUuid[0];
1179            }
1180
1181            AdapterService service = getService();
1182            if (service == null) {
1183                return new ParcelUuid[0];
1184            }
1185            return service.getRemoteUuids(device);
1186        }
1187
1188        @Override
1189        public boolean fetchRemoteUuids(BluetoothDevice device) {
1190            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1191                Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user");
1192                return false;
1193            }
1194
1195            AdapterService service = getService();
1196            if (service == null) {
1197                return false;
1198            }
1199            return service.fetchRemoteUuids(device);
1200        }
1201
1202
1203        @Override
1204        public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
1205            if (!Utils.checkCaller()) {
1206                Log.w(TAG, "setPin() - Not allowed for non-active user");
1207                return false;
1208            }
1209
1210            AdapterService service = getService();
1211            if (service == null) {
1212                return false;
1213            }
1214            return service.setPin(device, accept, len, pinCode);
1215        }
1216
1217        @Override
1218        public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
1219            if (!Utils.checkCaller()) {
1220                Log.w(TAG, "setPasskey() - Not allowed for non-active user");
1221                return false;
1222            }
1223
1224            AdapterService service = getService();
1225            if (service == null) {
1226                return false;
1227            }
1228            return service.setPasskey(device, accept, len, passkey);
1229        }
1230
1231        @Override
1232        public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
1233            if (!Utils.checkCaller()) {
1234                Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user");
1235                return false;
1236            }
1237
1238            AdapterService service = getService();
1239            if (service == null) {
1240                return false;
1241            }
1242            return service.setPairingConfirmation(device, accept);
1243        }
1244
1245        @Override
1246        public int getPhonebookAccessPermission(BluetoothDevice device) {
1247            if (!Utils.checkCaller()) {
1248                Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user");
1249                return BluetoothDevice.ACCESS_UNKNOWN;
1250            }
1251
1252            AdapterService service = getService();
1253            if (service == null) {
1254                return BluetoothDevice.ACCESS_UNKNOWN;
1255            }
1256            return service.getPhonebookAccessPermission(device);
1257        }
1258
1259        @Override
1260        public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) {
1261            if (!Utils.checkCaller()) {
1262                Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user");
1263                return false;
1264            }
1265
1266            AdapterService service = getService();
1267            if (service == null) {
1268                return false;
1269            }
1270            return service.setPhonebookAccessPermission(device, value);
1271        }
1272
1273        @Override
1274        public int getMessageAccessPermission(BluetoothDevice device) {
1275            if (!Utils.checkCaller()) {
1276                Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user");
1277                return BluetoothDevice.ACCESS_UNKNOWN;
1278            }
1279
1280            AdapterService service = getService();
1281            if (service == null) {
1282                return BluetoothDevice.ACCESS_UNKNOWN;
1283            }
1284            return service.getMessageAccessPermission(device);
1285        }
1286
1287        @Override
1288        public boolean setMessageAccessPermission(BluetoothDevice device, int value) {
1289            if (!Utils.checkCaller()) {
1290                Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user");
1291                return false;
1292            }
1293
1294            AdapterService service = getService();
1295            if (service == null) {
1296                return false;
1297            }
1298            return service.setMessageAccessPermission(device, value);
1299        }
1300
1301        @Override
1302        public int getSimAccessPermission(BluetoothDevice device) {
1303            if (!Utils.checkCaller()) {
1304                Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user");
1305                return BluetoothDevice.ACCESS_UNKNOWN;
1306            }
1307
1308            AdapterService service = getService();
1309            if (service == null) {
1310                return BluetoothDevice.ACCESS_UNKNOWN;
1311            }
1312            return service.getSimAccessPermission(device);
1313        }
1314
1315        @Override
1316        public boolean setSimAccessPermission(BluetoothDevice device, int value) {
1317            if (!Utils.checkCaller()) {
1318                Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user");
1319                return false;
1320            }
1321
1322            AdapterService service = getService();
1323            if (service == null) {
1324                return false;
1325            }
1326            return service.setSimAccessPermission(device, value);
1327        }
1328
1329        @Override
1330        public void sendConnectionStateChange(BluetoothDevice device, int profile, int state,
1331                int prevState) {
1332            AdapterService service = getService();
1333            if (service == null) {
1334                return;
1335            }
1336            service.sendConnectionStateChange(device, profile, state, prevState);
1337        }
1338
1339        @Override
1340        public IBluetoothSocketManager getSocketManager() {
1341            AdapterService service = getService();
1342            if (service == null) {
1343                return null;
1344            }
1345            return service.getSocketManager();
1346        }
1347
1348        @Override
1349        public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) {
1350            if (!Utils.checkCaller()) {
1351                Log.w(TAG, "sdpSea(): not allowed for non-active user");
1352                return false;
1353            }
1354
1355            AdapterService service = getService();
1356            if (service == null) {
1357                return false;
1358            }
1359            return service.sdpSearch(device, uuid);
1360        }
1361
1362        @Override
1363        public int getBatteryLevel(BluetoothDevice device) {
1364            if (!Utils.checkCaller()) {
1365                Log.w(TAG, "getBatteryLevel(): not allowed for non-active user");
1366                return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
1367            }
1368
1369            AdapterService service = getService();
1370            if (service == null) {
1371                return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
1372            }
1373            return service.getBatteryLevel(device);
1374        }
1375
1376        @Override
1377        public int getMaxConnectedAudioDevices() {
1378            // don't check caller, may be called from system UI
1379            AdapterService service = getService();
1380            if (service == null) {
1381                return AdapterProperties.MIN_CONNECTED_AUDIO_DEVICES;
1382            }
1383            return service.getMaxConnectedAudioDevices();
1384        }
1385
1386        @Override
1387        public boolean factoryReset() {
1388            AdapterService service = getService();
1389            if (service == null) {
1390                return false;
1391            }
1392            service.disable();
1393            return service.factoryReset();
1394
1395        }
1396
1397        @Override
1398        public void registerCallback(IBluetoothCallback cb) {
1399            AdapterService service = getService();
1400            if (service == null) {
1401                return;
1402            }
1403            service.registerCallback(cb);
1404        }
1405
1406        @Override
1407        public void unregisterCallback(IBluetoothCallback cb) {
1408            AdapterService service = getService();
1409            if (service == null) {
1410                return;
1411            }
1412            service.unregisterCallback(cb);
1413        }
1414
1415        @Override
1416        public boolean isMultiAdvertisementSupported() {
1417            AdapterService service = getService();
1418            if (service == null) {
1419                return false;
1420            }
1421            return service.isMultiAdvertisementSupported();
1422        }
1423
1424        @Override
1425        public boolean isOffloadedFilteringSupported() {
1426            AdapterService service = getService();
1427            if (service == null) {
1428                return false;
1429            }
1430            int val = service.getNumOfOffloadedScanFilterSupported();
1431            return (val >= MIN_OFFLOADED_FILTERS);
1432        }
1433
1434        @Override
1435        public boolean isOffloadedScanBatchingSupported() {
1436            AdapterService service = getService();
1437            if (service == null) {
1438                return false;
1439            }
1440            int val = service.getOffloadedScanResultStorage();
1441            return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES);
1442        }
1443
1444        @Override
1445        public boolean isLe2MPhySupported() {
1446            AdapterService service = getService();
1447            if (service == null) {
1448                return false;
1449            }
1450            return service.isLe2MPhySupported();
1451        }
1452
1453        @Override
1454        public boolean isLeCodedPhySupported() {
1455            AdapterService service = getService();
1456            if (service == null) {
1457                return false;
1458            }
1459            return service.isLeCodedPhySupported();
1460        }
1461
1462        @Override
1463        public boolean isLeExtendedAdvertisingSupported() {
1464            AdapterService service = getService();
1465            if (service == null) {
1466                return false;
1467            }
1468            return service.isLeExtendedAdvertisingSupported();
1469        }
1470
1471        @Override
1472        public boolean isLePeriodicAdvertisingSupported() {
1473            AdapterService service = getService();
1474            if (service == null) {
1475                return false;
1476            }
1477            return service.isLePeriodicAdvertisingSupported();
1478        }
1479
1480        @Override
1481        public int getLeMaximumAdvertisingDataLength() {
1482            AdapterService service = getService();
1483            if (service == null) {
1484                return 0;
1485            }
1486            return service.getLeMaximumAdvertisingDataLength();
1487        }
1488
1489        @Override
1490        public boolean isActivityAndEnergyReportingSupported() {
1491            AdapterService service = getService();
1492            if (service == null) {
1493                return false;
1494            }
1495            return service.isActivityAndEnergyReportingSupported();
1496        }
1497
1498        @Override
1499        public BluetoothActivityEnergyInfo reportActivityInfo() {
1500            AdapterService service = getService();
1501            if (service == null) {
1502                return null;
1503            }
1504            return service.reportActivityInfo();
1505        }
1506
1507        @Override
1508        public void requestActivityInfo(ResultReceiver result) {
1509            Bundle bundle = new Bundle();
1510            bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, reportActivityInfo());
1511            result.send(0, bundle);
1512        }
1513
1514        @Override
1515        public void onLeServiceUp() {
1516            AdapterService service = getService();
1517            if (service == null) {
1518                return;
1519            }
1520            service.onLeServiceUp();
1521        }
1522
1523        @Override
1524        public void onBrEdrDown() {
1525            AdapterService service = getService();
1526            if (service == null) {
1527                return;
1528            }
1529            service.onBrEdrDown();
1530        }
1531
1532        @Override
1533        public void dump(FileDescriptor fd, String[] args) {
1534            PrintWriter writer = new PrintWriter(new FileOutputStream(fd));
1535            AdapterService service = getService();
1536            if (service == null) {
1537                return;
1538            }
1539            service.dump(fd, writer, args);
1540            writer.close();
1541        }
1542    }
1543
1544    ;
1545
1546    // ----API Methods--------
1547
1548    public boolean isEnabled() {
1549        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1550        return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
1551    }
1552
1553    public int getState() {
1554        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1555        if (mAdapterProperties != null) {
1556            return mAdapterProperties.getState();
1557        }
1558        return BluetoothAdapter.STATE_OFF;
1559    }
1560
1561    public boolean enable() {
1562        return enable(false);
1563    }
1564
1565    public boolean enableNoAutoConnect() {
1566        return enable(true);
1567    }
1568
1569    public synchronized boolean enable(boolean quietMode) {
1570        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1571
1572        // Enforce the user restriction for disallowing Bluetooth if it was set.
1573        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
1574            debugLog("enable() called when Bluetooth was disallowed");
1575            return false;
1576        }
1577
1578        debugLog("enable() - Enable called with quiet mode status =  " + quietMode);
1579        mQuietmode = quietMode;
1580        Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
1581        mAdapterStateMachine.sendMessage(m);
1582        return true;
1583    }
1584
1585    boolean disable() {
1586        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1587
1588        debugLog("disable() called...");
1589        Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF);
1590        mAdapterStateMachine.sendMessage(m);
1591        return true;
1592    }
1593
1594    String getAddress() {
1595        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1596        enforceCallingOrSelfPermission(LOCAL_MAC_ADDRESS_PERM, "Need LOCAL_MAC_ADDRESS permission");
1597
1598        String addrString = null;
1599        byte[] address = mAdapterProperties.getAddress();
1600        return Utils.getAddressStringFromByte(address);
1601    }
1602
1603    ParcelUuid[] getUuids() {
1604        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1605
1606        return mAdapterProperties.getUuids();
1607    }
1608
1609    public String getName() {
1610        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1611
1612        try {
1613            return mAdapterProperties.getName();
1614        } catch (Throwable t) {
1615            debugLog("getName() - Unexpected exception (" + t + ")");
1616        }
1617        return null;
1618    }
1619
1620    boolean setName(String name) {
1621        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1622
1623        return mAdapterProperties.setName(name);
1624    }
1625
1626    BluetoothClass getBluetoothClass() {
1627        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1628
1629        return mAdapterProperties.getBluetoothClass();
1630    }
1631
1632    /**
1633     * Sets the Bluetooth CoD on the local adapter and also modifies the storage config for it.
1634     *
1635     * <p>Once set, this value persists across reboots.
1636     */
1637    boolean setBluetoothClass(BluetoothClass bluetoothClass) {
1638        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
1639                "Need BLUETOOTH PRIVILEGED permission");
1640        debugLog("setBluetoothClass() to " + bluetoothClass);
1641        boolean result = mAdapterProperties.setBluetoothClass(bluetoothClass);
1642        if (!result) {
1643            Log.e(TAG, "setBluetoothClass() to " + bluetoothClass + " failed");
1644        }
1645
1646        return result && storeBluetoothClassConfig(bluetoothClass.getClassOfDevice());
1647    }
1648
1649    int getScanMode() {
1650        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1651
1652        return mAdapterProperties.getScanMode();
1653    }
1654
1655    boolean setScanMode(int mode, int duration) {
1656        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1657
1658        setDiscoverableTimeout(duration);
1659
1660        int newMode = convertScanModeToHal(mode);
1661        return mAdapterProperties.setScanMode(newMode);
1662    }
1663
1664    int getDiscoverableTimeout() {
1665        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1666
1667        return mAdapterProperties.getDiscoverableTimeout();
1668    }
1669
1670    boolean setDiscoverableTimeout(int timeout) {
1671        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1672
1673        return mAdapterProperties.setDiscoverableTimeout(timeout);
1674    }
1675
1676    boolean startDiscovery() {
1677        debugLog("startDiscovery");
1678        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1679
1680        return startDiscoveryNative();
1681    }
1682
1683    boolean cancelDiscovery() {
1684        debugLog("cancelDiscovery");
1685        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1686
1687        return cancelDiscoveryNative();
1688    }
1689
1690    boolean isDiscovering() {
1691        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1692
1693        return mAdapterProperties.isDiscovering();
1694    }
1695
1696    long getDiscoveryEndMillis() {
1697        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1698
1699        return mAdapterProperties.discoveryEndMillis();
1700    }
1701
1702    /**
1703     * Same as API method {@link BluetoothAdapter#getBondedDevices()}
1704     *
1705     * @return array of bonded {@link BluetoothDevice} or null on error
1706     */
1707    public BluetoothDevice[] getBondedDevices() {
1708        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1709        return mAdapterProperties.getBondedDevices();
1710    }
1711
1712    int getAdapterConnectionState() {
1713        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1714        return mAdapterProperties.getConnectionState();
1715    }
1716
1717    int getProfileConnectionState(int profile) {
1718        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1719
1720        return mAdapterProperties.getProfileConnectionState(profile);
1721    }
1722
1723    boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) {
1724        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1725        if (mSdpManager != null) {
1726            mSdpManager.sdpSearch(device, uuid);
1727            return true;
1728        } else {
1729            return false;
1730        }
1731    }
1732
1733    boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
1734        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1735        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1736        if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
1737            return false;
1738        }
1739
1740        mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
1741
1742        // Pairing is unreliable while scanning, so cancel discovery
1743        // Note, remove this when native stack improves
1744        cancelDiscoveryNative();
1745
1746        Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
1747        msg.obj = device;
1748        msg.arg1 = transport;
1749
1750        if (oobData != null) {
1751            Bundle oobDataBundle = new Bundle();
1752            oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
1753            msg.setData(oobDataBundle);
1754        }
1755        mBondStateMachine.sendMessage(msg);
1756        return true;
1757    }
1758
1759    public boolean isQuietModeEnabled() {
1760        debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode);
1761        return mQuietmode;
1762    }
1763
1764    public void updateUuids() {
1765        debugLog("updateUuids() - Updating UUIDs for bonded devices");
1766        BluetoothDevice[] bondedDevices = getBondedDevices();
1767        if (bondedDevices == null) {
1768            return;
1769        }
1770
1771        for (BluetoothDevice device : bondedDevices) {
1772            mRemoteDevices.updateUuids(device);
1773        }
1774    }
1775
1776    boolean cancelBondProcess(BluetoothDevice device) {
1777        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1778        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1779
1780        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1781        if (deviceProp != null) {
1782            deviceProp.setBondingInitiatedLocally(false);
1783        }
1784
1785        return cancelBondNative(addr);
1786    }
1787
1788    boolean removeBond(BluetoothDevice device) {
1789        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1790        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1791        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
1792            return false;
1793        }
1794        deviceProp.setBondingInitiatedLocally(false);
1795
1796        Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
1797        msg.obj = device;
1798        mBondStateMachine.sendMessage(msg);
1799        return true;
1800    }
1801
1802    /**
1803     * Get the bond state of a particular {@link BluetoothDevice}
1804     *
1805     * @param device remote device of interest
1806     * @return bond state <p>Possible values are
1807     * {@link BluetoothDevice#BOND_NONE},
1808     * {@link BluetoothDevice#BOND_BONDING},
1809     * {@link BluetoothDevice#BOND_BONDED}.
1810     */
1811    @VisibleForTesting
1812    public int getBondState(BluetoothDevice device) {
1813        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1814        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1815        if (deviceProp == null) {
1816            return BluetoothDevice.BOND_NONE;
1817        }
1818        return deviceProp.getBondState();
1819    }
1820
1821    boolean isBondingInitiatedLocally(BluetoothDevice device) {
1822        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1823        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1824        if (deviceProp == null) {
1825            return false;
1826        }
1827        return deviceProp.isBondingInitiatedLocally();
1828    }
1829
1830    long getSupportedProfiles() {
1831        return Config.getSupportedProfilesBitMask();
1832    }
1833
1834    int getConnectionState(BluetoothDevice device) {
1835        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1836        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1837        return getConnectionStateNative(addr);
1838    }
1839
1840    /**
1841     * Same as API method {@link BluetoothDevice#getName()}
1842     *
1843     * @param device remote device of interest
1844     * @return remote device name
1845     */
1846    public String getRemoteName(BluetoothDevice device) {
1847        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1848        if (mRemoteDevices == null) {
1849            return null;
1850        }
1851        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1852        if (deviceProp == null) {
1853            return null;
1854        }
1855        return deviceProp.getName();
1856    }
1857
1858    int getRemoteType(BluetoothDevice device) {
1859        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1860        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1861        if (deviceProp == null) {
1862            return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
1863        }
1864        return deviceProp.getDeviceType();
1865    }
1866
1867    String getRemoteAlias(BluetoothDevice device) {
1868        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1869        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1870        if (deviceProp == null) {
1871            return null;
1872        }
1873        return deviceProp.getAlias();
1874    }
1875
1876    boolean setRemoteAlias(BluetoothDevice device, String name) {
1877        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1878        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1879        if (deviceProp == null) {
1880            return false;
1881        }
1882        deviceProp.setAlias(device, name);
1883        return true;
1884    }
1885
1886    int getRemoteClass(BluetoothDevice device) {
1887        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1888        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1889        if (deviceProp == null) {
1890            return 0;
1891        }
1892
1893        return deviceProp.getBluetoothClass();
1894    }
1895
1896    /**
1897     * Get UUIDs for service supported by a remote device
1898     *
1899     * @param device the remote device that we want to get UUIDs from
1900     * @return
1901     */
1902    @VisibleForTesting
1903    public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
1904        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1905        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1906        if (deviceProp == null) {
1907            return null;
1908        }
1909        return deviceProp.getUuids();
1910    }
1911
1912    boolean fetchRemoteUuids(BluetoothDevice device) {
1913        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1914        mRemoteDevices.fetchUuids(device);
1915        return true;
1916    }
1917
1918    int getBatteryLevel(BluetoothDevice device) {
1919        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1920        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1921        if (deviceProp == null) {
1922            return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
1923        }
1924        return deviceProp.getBatteryLevel();
1925    }
1926
1927    boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
1928        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1929        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1930        // Only allow setting a pin in bonding state, or bonded state in case of security upgrade.
1931        if (deviceProp == null || (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING
1932                && deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) {
1933            return false;
1934        }
1935
1936        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1937        return pinReplyNative(addr, accept, len, pinCode);
1938    }
1939
1940    boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
1941        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1942        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1943        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1944            return false;
1945        }
1946
1947        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1948        return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
1949                Utils.byteArrayToInt(passkey));
1950    }
1951
1952    boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
1953        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
1954                "Need BLUETOOTH PRIVILEGED permission");
1955        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1956        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1957            return false;
1958        }
1959
1960        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1961        return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, accept,
1962                0);
1963    }
1964
1965    int getPhonebookAccessPermission(BluetoothDevice device) {
1966        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1967        SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
1968                Context.MODE_PRIVATE);
1969        if (!pref.contains(device.getAddress())) {
1970            return BluetoothDevice.ACCESS_UNKNOWN;
1971        }
1972        return pref.getBoolean(device.getAddress(), false) ? BluetoothDevice.ACCESS_ALLOWED
1973                : BluetoothDevice.ACCESS_REJECTED;
1974    }
1975
1976    boolean setPhonebookAccessPermission(BluetoothDevice device, int value) {
1977        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
1978                "Need BLUETOOTH PRIVILEGED permission");
1979        SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
1980                Context.MODE_PRIVATE);
1981        SharedPreferences.Editor editor = pref.edit();
1982        if (value == BluetoothDevice.ACCESS_UNKNOWN) {
1983            editor.remove(device.getAddress());
1984        } else {
1985            editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
1986        }
1987        editor.apply();
1988        return true;
1989    }
1990
1991    int getMessageAccessPermission(BluetoothDevice device) {
1992        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1993        SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
1994                Context.MODE_PRIVATE);
1995        if (!pref.contains(device.getAddress())) {
1996            return BluetoothDevice.ACCESS_UNKNOWN;
1997        }
1998        return pref.getBoolean(device.getAddress(), false) ? BluetoothDevice.ACCESS_ALLOWED
1999                : BluetoothDevice.ACCESS_REJECTED;
2000    }
2001
2002    boolean setMessageAccessPermission(BluetoothDevice device, int value) {
2003        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
2004                "Need BLUETOOTH PRIVILEGED permission");
2005        SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
2006                Context.MODE_PRIVATE);
2007        SharedPreferences.Editor editor = pref.edit();
2008        if (value == BluetoothDevice.ACCESS_UNKNOWN) {
2009            editor.remove(device.getAddress());
2010        } else {
2011            editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
2012        }
2013        editor.apply();
2014        return true;
2015    }
2016
2017    int getSimAccessPermission(BluetoothDevice device) {
2018        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2019        SharedPreferences pref =
2020                getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
2021        if (!pref.contains(device.getAddress())) {
2022            return BluetoothDevice.ACCESS_UNKNOWN;
2023        }
2024        return pref.getBoolean(device.getAddress(), false) ? BluetoothDevice.ACCESS_ALLOWED
2025                : BluetoothDevice.ACCESS_REJECTED;
2026    }
2027
2028    boolean setSimAccessPermission(BluetoothDevice device, int value) {
2029        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
2030                "Need BLUETOOTH PRIVILEGED permission");
2031        SharedPreferences pref =
2032                getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
2033        SharedPreferences.Editor editor = pref.edit();
2034        if (value == BluetoothDevice.ACCESS_UNKNOWN) {
2035            editor.remove(device.getAddress());
2036        } else {
2037            editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
2038        }
2039        editor.apply();
2040        return true;
2041    }
2042
2043    void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
2044        // TODO(BT) permission check?
2045        // Since this is a binder call check if Bluetooth is on still
2046        if (getState() == BluetoothAdapter.STATE_OFF) {
2047            return;
2048        }
2049
2050        mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
2051
2052    }
2053
2054    IBluetoothSocketManager getSocketManager() {
2055        android.os.IBinder obj = getSocketManagerNative();
2056        if (obj == null) {
2057            return null;
2058        }
2059
2060        return IBluetoothSocketManager.Stub.asInterface(obj);
2061    }
2062
2063    boolean factoryReset() {
2064        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
2065        return factoryResetNative();
2066    }
2067
2068    void registerCallback(IBluetoothCallback cb) {
2069        mCallbacks.register(cb);
2070    }
2071
2072    void unregisterCallback(IBluetoothCallback cb) {
2073        mCallbacks.unregister(cb);
2074    }
2075
2076    public int getNumOfAdvertisementInstancesSupported() {
2077        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2078        return mAdapterProperties.getNumOfAdvertisementInstancesSupported();
2079    }
2080
2081    public boolean isMultiAdvertisementSupported() {
2082        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2083        return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA;
2084    }
2085
2086    public boolean isRpaOffloadSupported() {
2087        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2088        return mAdapterProperties.isRpaOffloadSupported();
2089    }
2090
2091    public int getNumOfOffloadedIrkSupported() {
2092        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2093        return mAdapterProperties.getNumOfOffloadedIrkSupported();
2094    }
2095
2096    public int getNumOfOffloadedScanFilterSupported() {
2097        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2098        return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
2099    }
2100
2101    public int getOffloadedScanResultStorage() {
2102        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2103        return mAdapterProperties.getOffloadedScanResultStorage();
2104    }
2105
2106    private boolean isActivityAndEnergyReportingSupported() {
2107        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
2108        return mAdapterProperties.isActivityAndEnergyReportingSupported();
2109    }
2110
2111    public boolean isLe2MPhySupported() {
2112        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2113        return mAdapterProperties.isLe2MPhySupported();
2114    }
2115
2116    public boolean isLeCodedPhySupported() {
2117        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2118        return mAdapterProperties.isLeCodedPhySupported();
2119    }
2120
2121    public boolean isLeExtendedAdvertisingSupported() {
2122        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2123        return mAdapterProperties.isLeExtendedAdvertisingSupported();
2124    }
2125
2126    public boolean isLePeriodicAdvertisingSupported() {
2127        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2128        return mAdapterProperties.isLePeriodicAdvertisingSupported();
2129    }
2130
2131    public int getLeMaximumAdvertisingDataLength() {
2132        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2133        return mAdapterProperties.getLeMaximumAdvertisingDataLength();
2134    }
2135
2136    /**
2137     * Get the maximum number of connected audio devices.
2138     *
2139     * @return the maximum number of connected audio devices
2140     */
2141    public int getMaxConnectedAudioDevices() {
2142        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2143        return mAdapterProperties.getMaxConnectedAudioDevices();
2144    }
2145
2146    private BluetoothActivityEnergyInfo reportActivityInfo() {
2147        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
2148        if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON
2149                || !mAdapterProperties.isActivityAndEnergyReportingSupported()) {
2150            return null;
2151        }
2152
2153        // Pull the data. The callback will notify mEnergyInfoLock.
2154        readEnergyInfo();
2155
2156        synchronized (mEnergyInfoLock) {
2157            try {
2158                mEnergyInfoLock.wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS);
2159            } catch (InterruptedException e) {
2160                // Just continue, the energy data may be stale but we won't miss anything next time
2161                // we query.
2162            }
2163
2164            final BluetoothActivityEnergyInfo info =
2165                    new BluetoothActivityEnergyInfo(SystemClock.elapsedRealtime(),
2166                            mStackReportedState, mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs,
2167                            mEnergyUsedTotalVoltAmpSecMicro);
2168
2169            // Count the number of entries that have byte counts > 0
2170            int arrayLen = 0;
2171            for (int i = 0; i < mUidTraffic.size(); i++) {
2172                final UidTraffic traffic = mUidTraffic.valueAt(i);
2173                if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
2174                    arrayLen++;
2175                }
2176            }
2177
2178            // Copy the traffic objects whose byte counts are > 0 and reset the originals.
2179            final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null;
2180            int putIdx = 0;
2181            for (int i = 0; i < mUidTraffic.size(); i++) {
2182                final UidTraffic traffic = mUidTraffic.valueAt(i);
2183                if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
2184                    result[putIdx++] = traffic.clone();
2185                    traffic.setRxBytes(0);
2186                    traffic.setTxBytes(0);
2187                }
2188            }
2189
2190            info.setUidTraffic(result);
2191
2192            // Read on clear values; a record of data is created with
2193            // timstamp and new samples are collected until read again
2194            mStackReportedState = 0;
2195            mTxTimeTotalMs = 0;
2196            mRxTimeTotalMs = 0;
2197            mIdleTimeTotalMs = 0;
2198            mEnergyUsedTotalVoltAmpSecMicro = 0;
2199            return info;
2200        }
2201    }
2202
2203    public int getTotalNumOfTrackableAdvertisements() {
2204        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2205        return mAdapterProperties.getTotalNumOfTrackableAdvertisements();
2206    }
2207
2208    public void onLeServiceUp() {
2209        Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
2210        mAdapterStateMachine.sendMessage(m);
2211    }
2212
2213    public void onBrEdrDown() {
2214        Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
2215        mAdapterStateMachine.sendMessage(m);
2216    }
2217
2218    private static int convertScanModeToHal(int mode) {
2219        switch (mode) {
2220            case BluetoothAdapter.SCAN_MODE_NONE:
2221                return AbstractionLayer.BT_SCAN_MODE_NONE;
2222            case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
2223                return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
2224            case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
2225                return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
2226        }
2227        // errorLog("Incorrect scan mode in convertScanModeToHal");
2228        return -1;
2229    }
2230
2231    static int convertScanModeFromHal(int mode) {
2232        switch (mode) {
2233            case AbstractionLayer.BT_SCAN_MODE_NONE:
2234                return BluetoothAdapter.SCAN_MODE_NONE;
2235            case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
2236                return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
2237            case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
2238                return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
2239        }
2240        //errorLog("Incorrect scan mode in convertScanModeFromHal");
2241        return -1;
2242    }
2243
2244    // This function is called from JNI. It allows native code to set a single wake
2245    // alarm. If an alarm is already pending and a new request comes in, the alarm
2246    // will be rescheduled (i.e. the previously set alarm will be cancelled).
2247    private boolean setWakeAlarm(long delayMillis, boolean shouldWake) {
2248        synchronized (this) {
2249            if (mPendingAlarm != null) {
2250                mAlarmManager.cancel(mPendingAlarm);
2251            }
2252
2253            long wakeupTime = SystemClock.elapsedRealtime() + delayMillis;
2254            int type = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP
2255                    : AlarmManager.ELAPSED_REALTIME;
2256
2257            Intent intent = new Intent(ACTION_ALARM_WAKEUP);
2258            mPendingAlarm =
2259                    PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
2260            mAlarmManager.setExact(type, wakeupTime, mPendingAlarm);
2261            return true;
2262        }
2263    }
2264
2265    // This function is called from JNI. It allows native code to acquire a single wake lock.
2266    // If the wake lock is already held, this function returns success. Although this function
2267    // only supports acquiring a single wake lock at a time right now, it will eventually be
2268    // extended to allow acquiring an arbitrary number of wake locks. The current interface
2269    // takes |lockName| as a parameter in anticipation of that implementation.
2270    private boolean acquireWakeLock(String lockName) {
2271        synchronized (this) {
2272            if (mWakeLock == null) {
2273                mWakeLockName = lockName;
2274                mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
2275            }
2276
2277            if (!mWakeLock.isHeld()) {
2278                mWakeLock.acquire();
2279            }
2280        }
2281        return true;
2282    }
2283
2284    // This function is called from JNI. It allows native code to release a wake lock acquired
2285    // by |acquireWakeLock|. If the wake lock is not held, this function returns failure.
2286    // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is
2287    // needed here. See the comment for |acquireWakeLock| for an explanation of the interface.
2288    private boolean releaseWakeLock(String lockName) {
2289        synchronized (this) {
2290            if (mWakeLock == null) {
2291                errorLog("Repeated wake lock release; aborting release: " + lockName);
2292                return false;
2293            }
2294
2295            if (mWakeLock.isHeld()) {
2296                mWakeLock.release();
2297            }
2298        }
2299        return true;
2300    }
2301
2302    private void energyInfoCallback(int status, int ctrlState, long txTime, long rxTime,
2303            long idleTime, long energyUsed, UidTraffic[] data) throws RemoteException {
2304        if (ctrlState >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID
2305                && ctrlState <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) {
2306            // Energy is product of mA, V and ms. If the chipset doesn't
2307            // report it, we have to compute it from time
2308            if (energyUsed == 0) {
2309                try {
2310                    final long txMah = Math.multiplyExact(txTime, getTxCurrentMa());
2311                    final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa());
2312                    final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa());
2313                    energyUsed = (long) (Math.addExact(Math.addExact(txMah, rxMah), idleMah)
2314                            * getOperatingVolt());
2315                } catch (ArithmeticException e) {
2316                    Slog.wtf(TAG, "overflow in bluetooth energy callback", e);
2317                    // Energy is already 0 if the exception was thrown.
2318                }
2319            }
2320
2321            synchronized (mEnergyInfoLock) {
2322                mStackReportedState = ctrlState;
2323                long totalTxTimeMs;
2324                long totalRxTimeMs;
2325                long totalIdleTimeMs;
2326                long totalEnergy;
2327                try {
2328                    totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime);
2329                    totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime);
2330                    totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime);
2331                    totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed);
2332                } catch (ArithmeticException e) {
2333                    // This could be because we accumulated a lot of time, or we got a very strange
2334                    // value from the controller (more likely). Discard this data.
2335                    Slog.wtf(TAG, "overflow in bluetooth energy callback", e);
2336                    totalTxTimeMs = mTxTimeTotalMs;
2337                    totalRxTimeMs = mRxTimeTotalMs;
2338                    totalIdleTimeMs = mIdleTimeTotalMs;
2339                    totalEnergy = mEnergyUsedTotalVoltAmpSecMicro;
2340                }
2341
2342                mTxTimeTotalMs = totalTxTimeMs;
2343                mRxTimeTotalMs = totalRxTimeMs;
2344                mIdleTimeTotalMs = totalIdleTimeMs;
2345                mEnergyUsedTotalVoltAmpSecMicro = totalEnergy;
2346
2347                for (UidTraffic traffic : data) {
2348                    UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid());
2349                    if (existingTraffic == null) {
2350                        mUidTraffic.put(traffic.getUid(), traffic);
2351                    } else {
2352                        existingTraffic.addRxBytes(traffic.getRxBytes());
2353                        existingTraffic.addTxBytes(traffic.getTxBytes());
2354                    }
2355                }
2356                mEnergyInfoLock.notifyAll();
2357            }
2358        }
2359
2360        verboseLog("energyInfoCallback() status = " + status + "txTime = " + txTime + "rxTime = "
2361                + rxTime + "idleTime = " + idleTime + "energyUsed = " + energyUsed + "ctrlState = "
2362                + ctrlState + "traffic = " + Arrays.toString(data));
2363    }
2364
2365    private int getIdleCurrentMa() {
2366        return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma);
2367    }
2368
2369    private int getTxCurrentMa() {
2370        return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma);
2371    }
2372
2373    private int getRxCurrentMa() {
2374        return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma);
2375    }
2376
2377    private double getOperatingVolt() {
2378        return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0;
2379    }
2380
2381    @Override
2382    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2383        enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
2384
2385        if (args.length == 0) {
2386            writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section.");
2387            writer.println("Use --print argument for dumpsys direct from AdapterService.");
2388            return;
2389        }
2390
2391        verboseLog("dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args));
2392        if (args[0].equals("--proto-bin")) {
2393            dumpMetrics(fd);
2394            return;
2395        }
2396
2397        writer.println("Bonded devices:");
2398        for (BluetoothDevice device : getBondedDevices()) {
2399            writer.println(
2400                    "  " + device.getAddress() + " [" + DEVICE_TYPE_NAMES[device.getType()] + "] "
2401                            + device.getName());
2402        }
2403
2404        StringBuilder sb = new StringBuilder();
2405        for (ProfileService profile : mRegisteredProfiles) {
2406            profile.dump(sb);
2407        }
2408
2409        writer.write(sb.toString());
2410        writer.flush();
2411
2412        dumpNative(fd, args);
2413    }
2414
2415    private void dumpMetrics(FileDescriptor fd) {
2416        BluetoothProto.BluetoothLog metrics = new BluetoothProto.BluetoothLog();
2417        metrics.setNumBondedDevices(getBondedDevices().length);
2418        for (ProfileService profile : mRegisteredProfiles) {
2419            profile.dumpProto(metrics);
2420        }
2421        byte[] nativeMetricsBytes = dumpMetricsNative();
2422        debugLog("dumpMetrics: native metrics size is " + nativeMetricsBytes.length);
2423        if (nativeMetricsBytes.length > 0) {
2424            try {
2425                metrics.mergeFrom(nativeMetricsBytes);
2426            } catch (InvalidProtocolBufferMicroException ex) {
2427                Log.w(TAG, "dumpMetrics: problem parsing metrics protobuf, " + ex.getMessage());
2428                return;
2429            }
2430        }
2431        byte[] metricsBytes = Base64.encode(metrics.toByteArray(), Base64.DEFAULT);
2432        debugLog("dumpMetrics: combined metrics size is " + metricsBytes.length);
2433        try (FileOutputStream protoOut = new FileOutputStream(fd)) {
2434            protoOut.write(metricsBytes);
2435        } catch (IOException e) {
2436            errorLog("dumpMetrics: error writing combined protobuf to fd, " + e.getMessage());
2437        }
2438    }
2439
2440    private void debugLog(String msg) {
2441        if (DBG) {
2442            Log.d(TAG, msg);
2443        }
2444    }
2445
2446    private void verboseLog(String msg) {
2447        if (VERBOSE) {
2448            Log.v(TAG, msg);
2449        }
2450    }
2451
2452    private void errorLog(String msg) {
2453        Log.e(TAG, msg);
2454    }
2455
2456    private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() {
2457        @Override
2458        public void onReceive(Context context, Intent intent) {
2459            synchronized (AdapterService.this) {
2460                mPendingAlarm = null;
2461                alarmFiredNative();
2462            }
2463        }
2464    };
2465
2466    private static native void classInitNative();
2467
2468    native boolean initNative();
2469
2470    native void cleanupNative();
2471
2472    /*package*/
2473    native boolean enableNative(boolean startRestricted);
2474
2475    /*package*/
2476    native boolean disableNative();
2477
2478    /*package*/
2479    native boolean setAdapterPropertyNative(int type, byte[] val);
2480
2481    /*package*/
2482    native boolean getAdapterPropertiesNative();
2483
2484    /*package*/
2485    native boolean getAdapterPropertyNative(int type);
2486
2487    /*package*/
2488    native boolean setAdapterPropertyNative(int type);
2489
2490    /*package*/
2491    native boolean setDevicePropertyNative(byte[] address, int type, byte[] val);
2492
2493    /*package*/
2494    native boolean getDevicePropertyNative(byte[] address, int type);
2495
2496    /*package*/
2497    native boolean createBondNative(byte[] address, int transport);
2498
2499    /*package*/
2500    native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData);
2501
2502    /*package*/
2503    native boolean removeBondNative(byte[] address);
2504
2505    /*package*/
2506    native boolean cancelBondNative(byte[] address);
2507
2508    /*package*/
2509    native boolean sdpSearchNative(byte[] address, byte[] uuid);
2510
2511    /*package*/
2512    native int getConnectionStateNative(byte[] address);
2513
2514    private native boolean startDiscoveryNative();
2515
2516    private native boolean cancelDiscoveryNative();
2517
2518    private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin);
2519
2520    private native boolean sspReplyNative(byte[] address, int type, boolean accept, int passkey);
2521
2522    /*package*/
2523    native boolean getRemoteServicesNative(byte[] address);
2524
2525    /*package*/
2526    native boolean getRemoteMasInstancesNative(byte[] address);
2527
2528    private native int readEnergyInfo();
2529
2530    private native IBinder getSocketManagerNative();
2531
2532    private native void setSystemUiUidNative(int systemUiUid);
2533
2534    private static native void setForegroundUserIdNative(int foregroundUserId);
2535
2536    /*package*/
2537    native boolean factoryResetNative();
2538
2539    private native void alarmFiredNative();
2540
2541    private native void dumpNative(FileDescriptor fd, String[] arguments);
2542
2543    private native byte[] dumpMetricsNative();
2544
2545    private native void interopDatabaseClearNative();
2546
2547    private native void interopDatabaseAddNative(int feature, byte[] address, int length);
2548
2549    // Returns if this is a mock object. This is currently used in testing so that we may not call
2550    // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up
2551    // calling finalize() which in turn calls System.exit() and the process crashes.
2552    //
2553    // Mock this in your testing framework to return true to avoid the mentioned behavior. In
2554    // production this has no effect.
2555    public boolean isMock() {
2556        return false;
2557    }
2558}
2559