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