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