1fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/*
2326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde* Copyright (C) 2014 Samsung System LSI
3fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Licensed under the Apache License, Version 2.0 (the "License");
4fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* you may not use this file except in compliance with the License.
5fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* You may obtain a copy of the License at
6fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*
7fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*      http://www.apache.org/licenses/LICENSE-2.0
8fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*
9fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Unless required by applicable law or agreed to in writing, software
10fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* distributed under the License is distributed on an "AS IS" BASIS,
11fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* See the License for the specific language governing permissions and
13fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* limitations under the License.
14fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*/
15fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
16fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepackage com.android.bluetooth.map;
17fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
18326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.app.AlarmManager;
19326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.app.PendingIntent;
20fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.bluetooth.BluetoothAdapter;
21fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.bluetooth.BluetoothDevice;
22bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.BluetoothMap;
23fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.bluetooth.BluetoothProfile;
24fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.bluetooth.BluetoothUuid;
25bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.IBluetoothMap;
26bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpMnsRecord;
27bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.content.BroadcastReceiver;
28fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.Context;
29fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.content.Intent;
30bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.content.IntentFilter;
31326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.content.IntentFilter.MalformedMimeTypeException;
3260e306ba5c132d5408ccae3a290e7cace020a49fSeven Shenimport android.Manifest;
33fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Handler;
341ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Guptaimport android.os.HandlerThread;
351ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Guptaimport android.os.Looper;
36fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Message;
3770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulzimport android.os.ParcelUuid;
38bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.os.PowerManager;
39326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.os.RemoteException;
40bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.provider.Settings;
41fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.text.TextUtils;
42fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Log;
43326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.util.SparseArray;
44fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
45fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.android.bluetooth.Utils;
46fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport com.android.bluetooth.btservice.AdapterService;
4770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulzimport com.android.bluetooth.btservice.ProfileService;
48326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
49bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport com.android.bluetooth.R;
50bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
51bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.io.IOException;
52bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.util.ArrayList;
53bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.util.HashMap;
54bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.util.List;
55bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.util.Set;
56fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
5770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulzpublic class BluetoothMapService extends ProfileService {
58fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final String TAG = "BluetoothMapService";
59fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
60fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    /**
61fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * To enable MAP DEBUG/VERBOSE logging - run below cmd in adb shell, and
62fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * restart com.android.bluetooth process. only enable DEBUG log:
63fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * "setprop log.tag.BluetoothMapService DEBUG"; enable both VERBOSE and
64fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * DEBUG log: "setprop log.tag.BluetoothMapService VERBOSE"
65fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     */
66fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
675a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public static final boolean DEBUG = true; //FIXME set to false;
68fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
69f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde    public static final boolean VERBOSE = false;
70fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
71fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    /**
72fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * Intent indicating timeout for user confirmation, which is sent to
73fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * BluetoothMapActivity
74fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     */
75fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final String USER_CONFIRM_TIMEOUT_ACTION =
76326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            "com.android.bluetooth.map.USER_CONFIRM_TIMEOUT";
77326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final int USER_CONFIRM_TIMEOUT_VALUE = 25000;
78fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
79326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /** Intent indicating that the email settings activity should be opened*/
805a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public static final String ACTION_SHOW_MAPS_SETTINGS =
815a60e47497f21f64e6d79420dc4c56c1907df22akschulz            "android.btmap.intent.action.SHOW_MAPS_SETTINGS";
82fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
83fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int MSG_SERVERSESSION_CLOSE = 5000;
84fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
85fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int MSG_SESSION_ESTABLISHED = 5001;
86fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
87fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public static final int MSG_SESSION_DISCONNECTED = 5002;
88fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
89326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int MSG_MAS_CONNECT = 5003; // Send at MAS connect, including the MAS_ID
90326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int MSG_MAS_CONNECT_CANCEL = 5004; // Send at auth. declined
91fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
92326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int MSG_ACQUIRE_WAKE_LOCK = 5005;
93c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu
94326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int MSG_RELEASE_WAKE_LOCK = 5006;
95c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu
96fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala    public static final int MSG_MNS_SDP_SEARCH = 5007;
97fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala
98fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala    public static final int MSG_OBSERVER_REGISTRATION = 5008;
99fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala
100fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
101fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
102fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
103fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
104fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final int START_LISTENER = 1;
105fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
106fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final int USER_TIMEOUT = 2;
107fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
10870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private static final int DISCONNECT_MAP = 3;
109fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
110326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final int SHUTDOWN = 4;
111326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
112c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu    private static final int RELEASE_WAKE_LOCK_DELAY = 10000;
113c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu
114fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private PowerManager.WakeLock mWakeLock = null;
115fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
116326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final int UPDATE_MAS_INSTANCES = 5;
117fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
118326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int UPDATE_MAS_INSTANCES_ACCOUNT_ADDED = 0;
119326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int UPDATE_MAS_INSTANCES_ACCOUNT_REMOVED = 1;
120326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int UPDATE_MAS_INSTANCES_ACCOUNT_RENAMED = 2;
121326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public static final int UPDATE_MAS_INSTANCES_ACCOUNT_DISCONNECT = 3;
122fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
123326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final int MAS_ID_SMS_MMS = 0;
124fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
125326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private BluetoothAdapter mAdapter;
126fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
127fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private BluetoothMnsObexClient mBluetoothMnsObexClient = null;
128fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
129326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /* mMasInstances: A list of the active MasInstances with the key being the MasId */
130326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private SparseArray<BluetoothMapMasInstance> mMasInstances =
131326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            new SparseArray<BluetoothMapMasInstance>(1);
132326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /* mMasInstanceMap: A list of the active MasInstances with the key being the account */
1335a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private HashMap<BluetoothMapAccountItem, BluetoothMapMasInstance> mMasInstanceMap =
1345a60e47497f21f64e6d79420dc4c56c1907df22akschulz            new HashMap<BluetoothMapAccountItem, BluetoothMapMasInstance>(1);
135fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1364786e5fffff14d92b795084b4470b785de66dfd0ugo_yu    private static BluetoothDevice mRemoteDevice = null; // The remote connected device - protect access
137fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1385a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private ArrayList<BluetoothMapAccountItem> mEnabledAccounts = null;
139fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static String sRemoteDeviceName = null;
140fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
141fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private int mState;
1425a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private BluetoothMapAppObserver mAppObserver = null;
143326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private AlarmManager mAlarmManager = null;
144fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
145326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mIsWaitingAuthorization = false;
146326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mRemoveTimeoutMsg = false;
1475cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta    private boolean mRegisteredMapReceiver = false;
148fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee    private int mPermission = BluetoothDevice.ACCESS_UNKNOWN;
149326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean mAccountChanged = false;
150bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private boolean mSdpSearchInitiated = false;
151bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    SdpMnsRecord mMnsRecord = null;
1521ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta    private MapServiceMessageHandler mSessionStatusHandler;
1535cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta    private boolean mStartError = true;
154326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
1554d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi    private boolean mSmsCapable = true;
1564d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi
157326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    // package and class name to which we send intent to check phone book access permission
158326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings";
159326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final String ACCESS_AUTHORITY_CLASS =
160326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        "com.android.settings.bluetooth.BluetoothPermissionRequest";
161fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
16270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private static final ParcelUuid[] MAP_UUIDS = {
16370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        BluetoothUuid.MAP,
16470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        BluetoothUuid.MNS,
16570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    };
16670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
167fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public BluetoothMapService() {
168fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        mState = BluetoothMap.STATE_DISCONNECTED;
169fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
170fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
171fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
1725a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1731ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta    private synchronized void closeService() {
174326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (DEBUG) Log.d(TAG, "MAP Service closeService in");
175fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
176326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (mBluetoothMnsObexClient != null) {
177326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mBluetoothMnsObexClient.shutdown();
178326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mBluetoothMnsObexClient = null;
17970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
1801ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (mMasInstances.size() > 0) {
1811ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            for (int i=0, c=mMasInstances.size(); i < c; i++) {
1821ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                mMasInstances.valueAt(i).shutdown();
1831ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            }
1841ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            mMasInstances.clear();
185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
18670bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu
187326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mIsWaitingAuthorization = false;
188fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        mPermission = BluetoothDevice.ACCESS_UNKNOWN;
189326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        setState(BluetoothMap.STATE_DISCONNECTED);
19070bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu
19170bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu        if (mWakeLock != null) {
19270bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu            mWakeLock.release();
193f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde            if (VERBOSE) Log.v(TAG, "CloseService(): Release Wake Lock");
19470bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu            mWakeLock = null;
19570bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu        }
1961ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        /* Only one SHUTDOWN message expected to closeService.
1971ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta         * Hence, quit looper and Handler on first SHUTDOWN message*/
1981ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (mSessionStatusHandler != null) {
1991ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            //Perform cleanup in Handler running on worker Thread
2001ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            mSessionStatusHandler.removeCallbacksAndMessages(null);
2011ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            Looper looper = mSessionStatusHandler.getLooper();
2021ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            if (looper != null) {
2031ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                looper.quit();
2041ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                if(VERBOSE) Log.i(TAG, "Quit looper");
2051ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            }
2061ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            mSessionStatusHandler = null;
2071ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            if(VERBOSE) Log.i(TAG, "Remove Handler");
2081ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        }
209326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mRemoteDevice = null;
21070bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu
211326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (VERBOSE) Log.v(TAG, "MAP Service closeService out");
212326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
21370bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu
214326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
215bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Starts the RFComm listener threads for each MAS
216326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @throws IOException
217326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
218bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private final void startRfcommSocketListeners(int masId) {
219bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(masId == -1) {
220bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            for(int i=0, c=mMasInstances.size(); i < c; i++) {
221bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                mMasInstances.valueAt(i).startRfcommSocketListener();
222bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
223bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        } else {
224bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            BluetoothMapMasInstance masInst = mMasInstances.get(masId); // returns null for -1
225bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(masInst != null) {
226bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                masInst.startRfcommSocketListener();
227bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            } else {
228bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.w(TAG, "startRfcommSocketListeners(): Invalid MasId: " + masId);
229bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
23070bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu        }
231fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
232fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
233326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
234326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Start a MAS instance for SMS/MMS and each e-mail account.
235326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
236326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private final void startObexServerSessions() {
237326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (DEBUG) Log.d(TAG, "Map Service START ObexServerSessions()");
238fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
239fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        // acquire the wakeLock before start Obex transaction thread
240fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (mWakeLock == null) {
241fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
242fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
243fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    "StartingObexMapTransaction");
244fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mWakeLock.setReferenceCounted(false);
245fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mWakeLock.acquire();
246f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde            if (VERBOSE) Log.v(TAG, "startObexSessions(): Acquire Wake Lock");
247fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
248fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
249326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mBluetoothMnsObexClient == null) {
250bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mBluetoothMnsObexClient =
251bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    new BluetoothMnsObexClient(mRemoteDevice, mMnsRecord, mSessionStatusHandler);
252326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
253326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
254326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean connected = false;
255326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        for(int i=0, c=mMasInstances.size(); i < c; i++) {
256326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            try {
257326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(mMasInstances.valueAt(i)
258326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        .startObexServerSession(mBluetoothMnsObexClient) == true) {
259326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    connected = true;
260326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
261326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } catch (IOException e) {
262bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.w(TAG,"IOException occured while starting an obexServerSession restarting" +
263bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        " the listener",e);
264326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mMasInstances.valueAt(i).restartObexServerSession();
265326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } catch (RemoteException e) {
266bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.w(TAG,"RemoteException occured while starting an obexServerSession restarting" +
267bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        " the listener",e);
268326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mMasInstances.valueAt(i).restartObexServerSession();
269326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
270326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
271326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(connected) {
272326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            setState(BluetoothMap.STATE_CONNECTED);
273fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
274c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu
275c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu        mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
276c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu        mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
277326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                .obtainMessage(MSG_RELEASE_WAKE_LOCK), RELEASE_WAKE_LOCK_DELAY);
278c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu
279f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde        if (VERBOSE) Log.v(TAG, "startObexServerSessions() success!");
280fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
281fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
282326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public Handler getHandler() {
283326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return mSessionStatusHandler;
284fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
285fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
286fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    /**
287326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Restart a MAS instances.
288326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param masId use -1 to stop all instances
289fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     */
290326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void stopObexServerSessions(int masId) {
291326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (DEBUG) Log.d(TAG, "MAP Service STOP ObexServerSessions()");
292fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
293326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean lastMasInst = true;
294fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
295326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(masId != -1) {
296326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            for(int i=0, c=mMasInstances.size(); i < c; i++) {
297326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                BluetoothMapMasInstance masInst = mMasInstances.valueAt(i);
298326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(masInst.getMasId() != masId && masInst.isStarted()) {
299326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    lastMasInst = false;
300fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                }
301fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
302326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } // Else just close down it all
303fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
304326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /* Shutdown the MNS client - currently must happen before MAS close */
305326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mBluetoothMnsObexClient != null && lastMasInst) {
306326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mBluetoothMnsObexClient.shutdown();
307326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mBluetoothMnsObexClient = null;
308326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
30943b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta
310326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapMasInstance masInst = mMasInstances.get(masId); // returns null for -1
311326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(masInst != null) {
312326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            masInst.restartObexServerSession();
3131ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        } else  if(masId == -1) {
314326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            for(int i=0, c=mMasInstances.size(); i < c; i++) {
315326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mMasInstances.valueAt(i).restartObexServerSession();
316326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
317326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
318fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
319326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(lastMasInst) {
320326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            setState(BluetoothMap.STATE_DISCONNECTED);
321fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            mPermission = BluetoothDevice.ACCESS_UNKNOWN;
322326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mRemoteDevice = null;
323326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(mAccountChanged) {
324326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                updateMasInstances(UPDATE_MAS_INSTANCES_ACCOUNT_DISCONNECT);
325fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
326fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
327fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
328326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // Release the wake lock at disconnect
329326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (mWakeLock != null && lastMasInst) {
330326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mSessionStatusHandler.removeMessages(MSG_ACQUIRE_WAKE_LOCK);
331326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
332326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mWakeLock.release();
333f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde            if (VERBOSE) Log.v(TAG, "stopObexServerSessions(): Release Wake Lock");
334fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
335fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
336fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
3371ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta    private final class MapServiceMessageHandler extends Handler {
3381ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        private MapServiceMessageHandler(Looper looper) {
3391ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            super(looper);
3401ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        }
341fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        @Override
342fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        public void handleMessage(Message msg) {
343fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (VERBOSE) Log.v(TAG, "Handler(): got msg=" + msg.what);
344fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
345fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            switch (msg.what) {
346326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                case UPDATE_MAS_INSTANCES:
347326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    updateMasInstancesHandler();
348326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    break;
349fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                case START_LISTENER:
350fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    if (mAdapter.isEnabled()) {
351bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        startRfcommSocketListeners(msg.arg1);
352fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    }
353fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
354326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                case MSG_MAS_CONNECT:
355326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    onConnectHandler(msg.arg1);
356326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    break;
357326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                case MSG_MAS_CONNECT_CANCEL:
358bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    /* TODO: We need to handle this by accepting the connection and reject at
359bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                     * OBEX level, by using ObexRejectServer - add timeout to handle clients not
360bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                     * closing the transport channel.
361bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                     */
362326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    stopObexServerSessions(-1);
363326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    break;
364fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                case USER_TIMEOUT:
365fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    if (mIsWaitingAuthorization){
366326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
367326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
368326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
369326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
370326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                        BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS);
371326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        sendBroadcast(intent);
372326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        cancelUserTimeoutAlarm();
373326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        mIsWaitingAuthorization = false;
374326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        stopObexServerSessions(-1);
375326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
376fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
377fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                case MSG_SERVERSESSION_CLOSE:
378326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    stopObexServerSessions(msg.arg1);
379fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
380fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                case MSG_SESSION_ESTABLISHED:
381fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
382fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                case MSG_SESSION_DISCONNECTED:
383fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    // handled elsewhere
384fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
38570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                case DISCONNECT_MAP:
38670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    disconnectMap((BluetoothDevice)msg.obj);
387fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
388326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                case SHUTDOWN:
389326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* Ensure to call close from this handler to avoid starting new stuff
390326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                       because of pending messages */
391326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    closeService();
392326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    break;
393c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                case MSG_ACQUIRE_WAKE_LOCK:
394f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    if (VERBOSE) Log.v(TAG, "Acquire Wake Lock request message");
395c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    if (mWakeLock == null) {
396c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                        PowerManager pm = (PowerManager)getSystemService(
397c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                                          Context.POWER_SERVICE);
398c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
399c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                                    "StartingObexMapTransaction");
400c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                        mWakeLock.setReferenceCounted(false);
401326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
402326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(!mWakeLock.isHeld()) {
403c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                        mWakeLock.acquire();
404f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                        if (DEBUG) Log.d(TAG, "  Acquired Wake Lock by message");
405c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    }
406c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
407c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
408c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                      .obtainMessage(MSG_RELEASE_WAKE_LOCK), RELEASE_WAKE_LOCK_DELAY);
409c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    break;
410c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                case MSG_RELEASE_WAKE_LOCK:
411f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    if (VERBOSE) Log.v(TAG, "Release Wake Lock request message");
412c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    if (mWakeLock != null) {
413c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                        mWakeLock.release();
414f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                        if (DEBUG) Log.d(TAG, "  Released Wake Lock by message");
415c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    }
416c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu                    break;
417fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                case MSG_MNS_SDP_SEARCH:
418fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    if (mRemoteDevice != null) {
419fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        if (DEBUG) Log.d(TAG,"MNS SDP Initiate Search ..");
420fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        mRemoteDevice.sdpSearch(BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS);
421fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    } else {
422fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        Log.w(TAG, "remoteDevice info not available");
423fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    }
424fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    break;
425fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                case MSG_OBSERVER_REGISTRATION:
426fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    if (DEBUG) Log.d(TAG,"ContentObserver Registration MASID: " + msg.arg1
427fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        + " Enable: " + msg.arg2);
428fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    BluetoothMapMasInstance masInst = mMasInstances.get(msg.arg1);
4291682d51711c917a440be14a600eb8ab89ad36f61Ashwini Munigala                    if (masInst != null && masInst.mObserver != null) {
430fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        try {
431fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                            if (msg.arg2 == BluetoothMapAppParams.NOTIFICATION_STATUS_YES) {
432fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                                masInst.mObserver.registerObserver();
433fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                            } else {
434fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                                masInst.mObserver.unregisterObserver();
435fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                            }
436fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        } catch (RemoteException e) {
437fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                            Log.e(TAG,"ContentObserverRegistarion Failed: "+ e);
438fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        }
439fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    }
440fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    break;
441fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                default:
442fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    break;
443fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
444fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
445fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    };
446fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
447326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void onConnectHandler(int masId) {
4485a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if (mIsWaitingAuthorization == true || mRemoteDevice == null
449f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                || mSdpSearchInitiated == true) {
450326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return;
451326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
452326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        BluetoothMapMasInstance masInst = mMasInstances.get(masId);
453fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        // Need to ensure we are still allowed.
454fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        if (DEBUG) Log.d(TAG, "mPermission = " + mPermission);
455fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        if (mPermission == BluetoothDevice.ACCESS_ALLOWED) {
456326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            try {
457f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                if (VERBOSE) Log.v(TAG, "incoming connection accepted from: "
458fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        + sRemoteDeviceName + " automatically as trusted device");
459fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                if (mBluetoothMnsObexClient != null && masInst != null) {
460326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    masInst.startObexServerSession(mBluetoothMnsObexClient);
461326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                } else {
462326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    startObexServerSessions();
463326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
464326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } catch (IOException ex) {
465326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.e(TAG, "catch IOException starting obex server session", ex);
466326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } catch (RemoteException ex) {
467326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.e(TAG, "catch RemoteException starting obex server session", ex);
468326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
469326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
470326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
471fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee
472326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public int getState() {
47370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return mState;
47470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
47570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
4765cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta    protected boolean isMapStarted() {
4775cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        return !mStartError;
4785cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta    }
4794786e5fffff14d92b795084b4470b785de66dfd0ugo_yu    public static BluetoothDevice getRemoteDevice() {
48070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return mRemoteDevice;
48170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
482fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private void setState(int state) {
483fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        setState(state, BluetoothMap.RESULT_SUCCESS);
484fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
485fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
486fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private synchronized void setState(int state, int result) {
487fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        if (state != mState) {
488fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (DEBUG) Log.d(TAG, "Map state " + mState + " -> " + state + ", result = "
489fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                    + result);
490fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            int prevState = mState;
491fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            mState = state;
49270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Intent intent = new Intent(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
49370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
49470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            intent.putExtra(BluetoothProfile.EXTRA_STATE, mState);
495fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
496fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            sendBroadcast(intent, BLUETOOTH_PERM);
497fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            AdapterService s = AdapterService.getAdapterService();
498fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (s != null) {
499fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                s.onProfileConnectionStateChanged(mRemoteDevice, BluetoothProfile.MAP,
500fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                        mState, prevState);
501fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
502fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
503fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
504fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
50570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public static String getRemoteDeviceName() {
50670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return sRemoteDeviceName;
50770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
508fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
50970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public boolean disconnect(BluetoothDevice device) {
510bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mSessionStatusHandler.sendMessage(mSessionStatusHandler
511bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                .obtainMessage(DISCONNECT_MAP, 0, 0, device));
51270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return true;
51370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
514fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
51570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public boolean disconnectMap(BluetoothDevice device) {
51670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        boolean result = false;
51770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        if (DEBUG) Log.d(TAG, "disconnectMap");
5181ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (getRemoteDevice()!= null && getRemoteDevice().equals(device)) {
51970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            switch (mState) {
52070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                case BluetoothMap.STATE_CONNECTED:
521335b2b8f6f17c93a4c2b192c8e1b629e48b230b3PauloftheWest                    /* Disconnect all connections and restart all MAS instances */
522335b2b8f6f17c93a4c2b192c8e1b629e48b230b3PauloftheWest                    stopObexServerSessions(-1);
52370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    result = true;
52470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    break;
52570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                default:
52670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    break;
52770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
52870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
52970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return result;
53070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
531fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
53270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public List<BluetoothDevice> getConnectedDevices() {
53370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
53470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        synchronized(this) {
53570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (mState == BluetoothMap.STATE_CONNECTED && mRemoteDevice != null) {
53670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                devices.add(mRemoteDevice);
53770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            }
53870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
53970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return devices;
54070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
541fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
54270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
54370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
54470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
54570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        int connectionState;
54670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        synchronized (this) {
54770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            for (BluetoothDevice device : bondedDevices) {
54870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                ParcelUuid[] featureUuids = device.getUuids();
54970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                if (!BluetoothUuid.containsAnyUuid(featureUuids, MAP_UUIDS)) {
55070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    continue;
55170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
55270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                connectionState = getConnectionState(device);
55370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                for(int i = 0; i < states.length; i++) {
55470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    if (connectionState == states[i]) {
55570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                        deviceList.add(device);
55670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    }
55770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
55870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            }
55970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
56070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return deviceList;
56170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
562fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
56370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public int getConnectionState(BluetoothDevice device) {
56470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        synchronized(this) {
56570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (getState() == BluetoothMap.STATE_CONNECTED && getRemoteDevice().equals(device)) {
56670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                return BluetoothProfile.STATE_CONNECTED;
56770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            } else {
56870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                return BluetoothProfile.STATE_DISCONNECTED;
56970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            }
570fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
571fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
572fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
57370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public boolean setPriority(BluetoothDevice device, int priority) {
57470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        Settings.Global.putInt(getContentResolver(),
57570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Settings.Global.getBluetoothMapPriorityKey(device.getAddress()),
57670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            priority);
577f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde        if (VERBOSE) Log.v(TAG, "Saved priority " + device + " = " + priority);
57870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return true;
579fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
580fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
58170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public int getPriority(BluetoothDevice device) {
58270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        int priority = Settings.Global.getInt(getContentResolver(),
58370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            Settings.Global.getBluetoothMapPriorityKey(device.getAddress()),
58470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothProfile.PRIORITY_UNDEFINED);
58570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return priority;
586fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
587fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
58870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    @Override
58970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    protected IProfileServiceBinder initBinder() {
59070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return new BluetoothMapBinder(this);
59170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
592fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
59370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    @Override
59470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    protected boolean start() {
59570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        if (DEBUG) Log.d(TAG, "start()");
5965cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        if (isMapStarted()) {
5975cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            Log.w(TAG, "start received for already started, ignoring");
5985cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            return false;
5995cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        }
6001ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        HandlerThread thread = new HandlerThread("BluetoothMapHandler");
6011ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        thread.start();
6021ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        Looper looper = thread.getLooper();
6031ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        mSessionStatusHandler = new MapServiceMessageHandler(looper);
6041ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta
60570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        IntentFilter filter = new IntentFilter();
60670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
60770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
60843b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
609bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        filter.addAction(BluetoothDevice.ACTION_SDP_RECORD);
6105a60e47497f21f64e6d79420dc4c56c1907df22akschulz        filter.addAction(ACTION_SHOW_MAPS_SETTINGS);
611326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        filter.addAction(USER_CONFIRM_TIMEOUT_ACTION);
612326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
613326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // We need two filters, since Type only applies to the ACTION_MESSAGE_SENT
614326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        IntentFilter filterMessageSent = new IntentFilter();
615326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        filterMessageSent.addAction(BluetoothMapContentObserver.ACTION_MESSAGE_SENT);
616326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        try{
617326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            filterMessageSent.addDataType("message/*");
618326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } catch (MalformedMimeTypeException e) {
619326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.e(TAG, "Wrong mime type!!!", e);
620326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
6215cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        if (!mRegisteredMapReceiver) {
6225cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            try {
6235cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                registerReceiver(mMapReceiver, filter);
62460e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                // We need WRITE_SMS permission to handle messages in
62560e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                // actionMessageSentDisconnected()
62660e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                registerReceiver(mMapReceiver, filterMessageSent,
62760e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                                 Manifest.permission.WRITE_SMS, null);
6285cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                mRegisteredMapReceiver = true;
6295cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            } catch (Exception e) {
6305cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                Log.e(TAG,"Unable to register map receiver",e);
6315cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            }
63270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
63370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        mAdapter = BluetoothAdapter.getDefaultAdapter();
6345a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mAppObserver = new BluetoothMapAppObserver(this, this);
635326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
636326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mEnabledAccounts = mAppObserver.getEnabledAccountItems();
6374d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi
6384d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi        mSmsCapable = getResources().getBoolean(
6394d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                com.android.internal.R.bool.config_sms_capable);
640326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // Uses mEnabledAccounts, hence getEnabledAccountItems() must be called before this.
641326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        createMasInstances();
642326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
64370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        // start RFCOMM listener
644bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sendStartListenerMessage(-1);
6455cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        mStartError = false;
6465cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        return !mStartError;
64770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
648fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
649326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
650326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Call this to trigger an update of the MAS instance list.
651326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * No changes will be applied unless in disconnected state
652326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
653326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public void updateMasInstances(int action) {
654326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mSessionStatusHandler.obtainMessage (UPDATE_MAS_INSTANCES,
655326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    action, 0).sendToTarget();
656326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
657326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
658326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
659326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Update the active MAS Instances according the difference between mEnabledDevices
660326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * and the current list of accounts.
661326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Will only make changes if state is disconnected.
662326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *
663326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * How it works:
664326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * 1) Build lists of account changes from last update of mEnabledAccounts.
665326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *      newAccounts - accounts that have been enabled since mEnabledAccounts
666326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *                    was last updated.
667326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *      removedAccounts - Accounts that is on mEnabledAccounts, but no longer
668326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *                        enabled.
669326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *      enabledAccounts - A new list of all enabled accounts.
670326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * 2) Stop and remove all MasInstances on the remove list
671326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * 3) Add and start MAS instances for accounts on the new list.
672326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Called at:
673326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *  - Each change in accounts
674326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *  - Each disconnect - before MasInstances restart.
675326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *
676326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @return true is any changes are made, false otherwise.
677326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
678326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private boolean updateMasInstancesHandler(){
679f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde        if (DEBUG) Log.d(TAG,"updateMasInstancesHandler() state = " + getState());
680326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        boolean changed = false;
681326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
682326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(getState() == BluetoothMap.STATE_DISCONNECTED) {
6835a60e47497f21f64e6d79420dc4c56c1907df22akschulz            ArrayList<BluetoothMapAccountItem> newAccountList =
684bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mAppObserver.getEnabledAccountItems();
6855a60e47497f21f64e6d79420dc4c56c1907df22akschulz            ArrayList<BluetoothMapAccountItem> newAccounts = null;
6865a60e47497f21f64e6d79420dc4c56c1907df22akschulz            ArrayList<BluetoothMapAccountItem> removedAccounts = null;
6875a60e47497f21f64e6d79420dc4c56c1907df22akschulz            newAccounts = new ArrayList<BluetoothMapAccountItem>();
688bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            removedAccounts = mEnabledAccounts; // reuse the current enabled list, to track removed
689bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                                // accounts
6905a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for(BluetoothMapAccountItem account: newAccountList) {
691326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(!removedAccounts.remove(account)) {
692326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    newAccounts.add(account);
693326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
694326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
695326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
696326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(removedAccounts != null) {
697326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Remove all disabled/removed accounts */
6985a60e47497f21f64e6d79420dc4c56c1907df22akschulz                for(BluetoothMapAccountItem account : removedAccounts) {
699326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    BluetoothMapMasInstance masInst = mMasInstanceMap.remove(account);
700f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    if (VERBOSE) Log.v(TAG,"  Removing account: " + account + " masInst = " + masInst);
701326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(masInst != null) {
702326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        masInst.shutdown();
703326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        mMasInstances.remove(masInst.getMasId());
704326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        changed = true;
705326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
706326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
707326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
708326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
709326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(newAccounts != null) {
710326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                /* Add any newly created accounts */
7115a60e47497f21f64e6d79420dc4c56c1907df22akschulz                for(BluetoothMapAccountItem account : newAccounts) {
712f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    if (VERBOSE) Log.v(TAG,"  Adding account: " + account);
713326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    int masId = getNextMasId();
714326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    BluetoothMapMasInstance newInst =
715326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            new BluetoothMapMasInstance(this,
716326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                    this,
717326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                    account,
718326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                    masId,
719326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                    false);
720326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    mMasInstances.append(masId, newInst);
721326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    mMasInstanceMap.put(account, newInst);
722326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    changed = true;
723326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* Start the new instance */
724326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (mAdapter.isEnabled()) {
725326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        newInst.startRfcommSocketListener();
726326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
727326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
728326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
729326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mEnabledAccounts = newAccountList;
730f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde            if (VERBOSE) {
731f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                Log.v(TAG,"  Enabled accounts:");
7325a60e47497f21f64e6d79420dc4c56c1907df22akschulz                for(BluetoothMapAccountItem account : mEnabledAccounts) {
733f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    Log.v(TAG, "   " + account);
734326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
735f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                Log.v(TAG,"  Active MAS instances:");
736326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                for(int i=0, c=mMasInstances.size(); i < c; i++) {
737326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    BluetoothMapMasInstance masInst = mMasInstances.valueAt(i);
738f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    Log.v(TAG, "   " + masInst);
739326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
740326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
741326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mAccountChanged = false;
742326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } else {
743326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mAccountChanged = true;
744326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
745326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return changed;
746326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
747326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
748326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
749326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Will return the next MasId to use.
750326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Will ensure the key returned is greater than the largest key in use.
751326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Unless the key 255 is in use, in which case the first free masId
752326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * will be returned.
753326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @return
754326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
755326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private int getNextMasId() {
756326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /* Find the largest masId in use */
757326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        int largestMasId = 0;
758326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        for(int i=0, c=mMasInstances.size(); i < c; i++) {
759326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            int masId = mMasInstances.keyAt(i);
760326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(masId > largestMasId) {
761326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                largestMasId = masId;
762326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
763326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
764326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(largestMasId < 0xff) {
765326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            return largestMasId + 1;
766326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
767326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /* If 0xff is already in use, wrap and choose the first free
768326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde         * MasId. */
769326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        for(int i = 1; i <= 0xff; i++) {
770326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            if(mMasInstances.get(i) == null) {
771326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return i;
772326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
773326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
774326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return 0xff; // This will never happen, as we only allow 10 e-mail accounts to be enabled
775326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
776326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
777326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void createMasInstances() {
7784d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi        int masId = mSmsCapable ? MAS_ID_SMS_MMS : -1;
7794d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi
7804d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi        if (mSmsCapable) {
7814d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi            // Add the SMS/MMS instance
7824d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi            BluetoothMapMasInstance smsMmsInst =
7834d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                    new BluetoothMapMasInstance(this,
7844d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                            this,
7854d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                            null,
7864d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                            masId,
7874d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                            true);
7884d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi            mMasInstances.append(masId, smsMmsInst);
7894d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi            mMasInstanceMap.put(null, smsMmsInst);
7904d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi        }
791326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
792326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // get list of accounts already set to be visible through MAP
7935a60e47497f21f64e6d79420dc4c56c1907df22akschulz        for(BluetoothMapAccountItem account : mEnabledAccounts) {
794326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            masId++;  // SMS/MMS is masId=0, increment before adding next
795326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            BluetoothMapMasInstance newInst =
796326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    new BluetoothMapMasInstance(this,
797326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            this,
798326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            account,
799326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            masId,
800326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            false);
801326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mMasInstances.append(masId, newInst);
802326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mMasInstanceMap.put(account, newInst);
803326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
804326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
805326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
80670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    @Override
80770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    protected boolean stop() {
80870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        if (DEBUG) Log.d(TAG, "stop()");
8095cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        if (mRegisteredMapReceiver) {
8105cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            try {
8115cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                mRegisteredMapReceiver = false;
8125cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                unregisterReceiver(mMapReceiver);
8135cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                mAppObserver.shutdown();
8145cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            } catch (Exception e) {
8155cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta                Log.e(TAG,"Unable to unregister map receiver",e);
8165cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            }
817fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
8185cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        //Stop MapProfile if already started.
8195cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        //TODO: Check if the profile state can be retreived from ProfileService or AdapterService.
8205cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        if (!isMapStarted()) {
8215cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            if (DEBUG) Log.d(TAG, "Service Not Available to STOP, ignoring");
8225cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            return true;
8235cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        } else {
8245cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta            if (VERBOSE) Log.d(TAG, "Service Stoping()");
8255cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        }
8261ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (mSessionStatusHandler != null) {
8271ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            sendShutdownMessage();
8281ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        }
8295cd7c89d0e17a9176337a36a27792bab3dd76fe9Hemant Gupta        mStartError = true;
83070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        setState(BluetoothMap.STATE_DISCONNECTED, BluetoothMap.RESULT_CANCELED);
83170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return true;
83270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
83370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
83470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public boolean cleanup()  {
83570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        if (DEBUG) Log.d(TAG, "cleanup()");
83670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        setState(BluetoothMap.STATE_DISCONNECTED, BluetoothMap.RESULT_CANCELED);
8371ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        //Cleanup already handled in Stop().
8381ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        //Move this  extra check to Handler.
8391ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        sendShutdownMessage();
84070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return true;
84170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
84270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
843326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
844326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * Called from each MAS instance when a connection is received.
845326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param remoteDevice The device connecting
846326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @param masInst a reference to the calling MAS instance.
847326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @return
848326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
849326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public boolean onConnect(BluetoothDevice remoteDevice, BluetoothMapMasInstance masInst) {
850fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        boolean sendIntent = false;
851fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        boolean cancelConnection = false;
852326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
853326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        // As this can be called from each MasInstance, we need to lock access to member variables
854326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        synchronized(this) {
855fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            if (mRemoteDevice == null) {
856326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mRemoteDevice = remoteDevice;
857326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                sRemoteDeviceName = mRemoteDevice.getName();
858326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                // In case getRemoteName failed and return null
859326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (TextUtils.isEmpty(sRemoteDeviceName)) {
860326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sRemoteDeviceName = getString(R.string.defaultname);
861326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
862326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
863fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                mPermission = mRemoteDevice.getMessageAccessPermission();
864fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                if (mPermission == BluetoothDevice.ACCESS_UNKNOWN) {
865326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendIntent = true;
866326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    mIsWaitingAuthorization = true;
867326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    setUserTimeoutAlarm();
868fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                } else if (mPermission == BluetoothDevice.ACCESS_REJECTED) {
869fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    cancelConnection = true;
8705a60e47497f21f64e6d79420dc4c56c1907df22akschulz                } else if(mPermission == BluetoothDevice.ACCESS_ALLOWED) {
8715a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    mRemoteDevice.sdpSearch(BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS);
8725a60e47497f21f64e6d79420dc4c56c1907df22akschulz                    mSdpSearchInitiated = true;
873326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
874326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else if (!mRemoteDevice.equals(remoteDevice)) {
875326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                Log.w(TAG, "Unexpected connection from a second Remote Device received. name: " +
876326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            ((remoteDevice==null)?"unknown":remoteDevice.getName()));
877326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                return false; /* The connecting device is different from what is already
878326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                                 connected, reject the connection. */
879326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } // Else second connection to same device, just continue
880326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
881326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
882fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        if (sendIntent) {
883fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            // This will trigger Settings app's dialog.
884fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST);
885326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
886326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
887326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                            BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS);
888326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
889beb0497605ef61062d0565d85897f4c842845a8fAng Li            sendOrderedBroadcast(intent, BLUETOOTH_ADMIN_PERM);
890326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
891f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde            if (VERBOSE) Log.v(TAG, "waiting for authorization for connection from: "
892326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    + sRemoteDeviceName);
893326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            //Queue USER_TIMEOUT to disconnect MAP OBEX session. If user doesn't
894326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            //accept or reject authorization request
895fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        } else if (cancelConnection) {
896fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee            sendConnectCancelMessage();
897fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee        } else if (mPermission == BluetoothDevice.ACCESS_ALLOWED) {
898326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            /* Signal to the service that we have a incoming connection. */
899326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            sendConnectMessage(masInst.getMasId());
900326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
901326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        return true;
902326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    };
903326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
904326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
905326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void setUserTimeoutAlarm(){
906f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde        if (DEBUG) Log.d(TAG,"SetUserTimeOutAlarm()");
907326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mAlarmManager == null){
908326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mAlarmManager =(AlarmManager) this.getSystemService (Context.ALARM_SERVICE);
909326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
910326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mRemoveTimeoutMsg = true;
911326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        Intent timeoutIntent =
912326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                new Intent(USER_CONFIRM_TIMEOUT_ACTION);
913326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, timeoutIntent, 0);
914bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() +
915bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                USER_CONFIRM_TIMEOUT_VALUE,pIntent);
916326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
917326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
918326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void cancelUserTimeoutAlarm(){
919f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde        if (DEBUG) Log.d(TAG,"cancelUserTimeOutAlarm()");
9200f67816e838489474a0c3c57a8d856f6d51ba45fAshwini Munigala        Intent timeoutIntent = new Intent(USER_CONFIRM_TIMEOUT_ACTION);
9210f67816e838489474a0c3c57a8d856f6d51ba45fAshwini Munigala        PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, timeoutIntent, 0);
9220f67816e838489474a0c3c57a8d856f6d51ba45fAshwini Munigala        pIntent.cancel();
9230f67816e838489474a0c3c57a8d856f6d51ba45fAshwini Munigala
924326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
9250f67816e838489474a0c3c57a8d856f6d51ba45fAshwini Munigala        alarmManager.cancel(pIntent);
926326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        mRemoveTimeoutMsg = false;
927326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
928326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
929bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /**
930bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Start the incoming connection listeners for a MAS ID
931bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param masId the MasID to start. Use -1 to start all listeners.
932bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     */
933bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public void sendStartListenerMessage(int masId) {
9341ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (mSessionStatusHandler != null && ! mSessionStatusHandler.hasMessages(START_LISTENER)) {
935bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            Message msg = mSessionStatusHandler.obtainMessage(START_LISTENER, masId, 0);
936bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            /* We add a small delay here to ensure the call returns true before this message is
937bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde             * handled. It seems wrong to add a delay, but the alternative is to build a lock
938bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde             * system to handle synchronization, which isn't nice either... */
939bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSessionStatusHandler.sendMessageDelayed(msg, 20);
9401ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        } else if (mSessionStatusHandler != null) {
9411ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            if(DEBUG)
9421ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                Log.w(TAG, "mSessionStatusHandler START_LISTENER message already in Queue");
9431ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        }
944bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
945bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
946326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void sendConnectMessage(int masId) {
947326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mSessionStatusHandler != null) {
948326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Message msg = mSessionStatusHandler.obtainMessage(MSG_MAS_CONNECT, masId, 0);
949bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            /* We add a small delay here to ensure onConnect returns true before this message is
950bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde             * handled. It seems wrong, but the alternative is to store a reference to the
951bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde             * connection in this message, which isn't nice either... */
952bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSessionStatusHandler.sendMessageDelayed(msg, 20);
953326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } // Can only be null during shutdown
954326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
955326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void sendConnectTimeoutMessage() {
956326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (DEBUG) Log.d(TAG, "sendConnectTimeoutMessage()");
957326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mSessionStatusHandler != null) {
958326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Message msg = mSessionStatusHandler.obtainMessage(USER_TIMEOUT);
959326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.sendToTarget();
960326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } // Can only be null during shutdown
961326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
962326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void sendConnectCancelMessage() {
963326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if(mSessionStatusHandler != null) {
964326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Message msg = mSessionStatusHandler.obtainMessage(MSG_MAS_CONNECT_CANCEL);
965326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            msg.sendToTarget();
966326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        } // Can only be null during shutdown
967326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
968326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
969326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private void sendShutdownMessage() {
970326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        /* Any pending messages are no longer valid.
971326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        To speed up things, simply delete them. */
972326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (mRemoveTimeoutMsg) {
973326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Intent timeoutIntent =
974326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    new Intent(USER_CONFIRM_TIMEOUT_ACTION);
975326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            sendBroadcast(timeoutIntent, BLUETOOTH_PERM);
976326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            mIsWaitingAuthorization = false;
977326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            cancelUserTimeoutAlarm();
978326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        }
9791ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (mSessionStatusHandler != null && !mSessionStatusHandler.hasMessages(SHUTDOWN)) {
9801ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            mSessionStatusHandler.removeCallbacksAndMessages(null);
9811ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            // Request release of all resources
9821ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            Message msg = mSessionStatusHandler.obtainMessage(SHUTDOWN);
9831ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            if( mSessionStatusHandler.sendMessage(msg) == false) {
9841ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                /* most likely caused by shutdown being called from multiple sources - e.g.BT off
9851ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                 * signaled through intent and a service shutdown simultaneously.
9861ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                 * Intended behavior not documented, hence we need to be able to handle all cases*/
9871ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            } else {
9881ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                if(DEBUG)
9891ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                    Log.e(TAG, "mSessionStatusHandler.sendMessage() dispatched shutdown message");
9901ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta            }
9911ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        } else if (mSessionStatusHandler != null) {
9921ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                if(DEBUG)
9931ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta                    Log.w(TAG, "mSessionStatusHandler shutdown message already in Queue");
9941ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        }
9951ff5a0a6b42eff4c5728f0327440c127f8d3bb1cHemant Gupta        if (VERBOSE) Log.d(TAG, "sendShutdownMessage() Out");
996326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
99743b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta
99870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private MapBroadcastReceiver mMapReceiver = new MapBroadcastReceiver();
999fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
100070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private class MapBroadcastReceiver extends BroadcastReceiver {
100170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        @Override
100270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public void onReceive(Context context, Intent intent) {
100370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (DEBUG) Log.d(TAG, "onReceive");
100470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            String action = intent.getAction();
10055a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if (DEBUG) Log.d(TAG, "onReceive: " + action);
100670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
100770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
100870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                                               BluetoothAdapter.ERROR);
100970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                if (state == BluetoothAdapter.STATE_TURNING_OFF) {
1010326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if (DEBUG) Log.d(TAG, "STATE_TURNING_OFF");
1011326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendShutdownMessage();
101270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                } else if (state == BluetoothAdapter.STATE_ON) {
101370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    if (DEBUG) Log.d(TAG, "STATE_ON");
1014bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    // start ServerSocket listener threads
1015bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    sendStartListenerMessage(-1);
101670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
1017bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
1018326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }else if (action.equals(USER_CONFIRM_TIMEOUT_ACTION)){
1019326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (DEBUG) Log.d(TAG, "USER_CONFIRM_TIMEOUT ACTION Received.");
1020326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                // send us self a message about the timeout.
1021326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                sendConnectTimeoutMessage();
1022bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
102370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) {
1024bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
102570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
102670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                                               BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
1027bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
102870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                if (DEBUG) Log.d(TAG, "Received ACTION_CONNECTION_ACCESS_REPLY:" +
1029326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                           requestType + "isWaitingAuthorization:" + mIsWaitingAuthorization);
1030fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                if ((!mIsWaitingAuthorization)
1031fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        || (requestType != BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS)) {
103270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    // this reply is not for us
103370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    return;
103470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
103570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
1036326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                mIsWaitingAuthorization = false;
1037326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if (mRemoveTimeoutMsg) {
103843b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    mSessionStatusHandler.removeMessages(USER_TIMEOUT);
1039326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    cancelUserTimeoutAlarm();
1040326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    setState(BluetoothMap.STATE_DISCONNECTED);
104143b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                }
104270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
104370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                if (intent.getIntExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
1044fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                       BluetoothDevice.CONNECTION_ACCESS_NO)
1045fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        == BluetoothDevice.CONNECTION_ACCESS_YES) {
1046326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // Bluetooth connection accepted by user
1047fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    mPermission = BluetoothDevice.ACCESS_ALLOWED;
104870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    if (intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)) {
1049fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        boolean result = mRemoteDevice.setMessageAccessPermission(
1050fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                BluetoothDevice.ACCESS_ALLOWED);
1051fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        if (DEBUG) {
1052fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            Log.d(TAG, "setMessageAccessPermission(ACCESS_ALLOWED) result="
1053fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                    + result);
1054fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        }
105570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                    }
10565a60e47497f21f64e6d79420dc4c56c1907df22akschulz
1057bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mRemoteDevice.sdpSearch(BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS);
1058bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mSdpSearchInitiated = true;
105970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                } else {
1060326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // Auth. declined by user, serverSession should not be running, but
1061326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    // call stop anyway to restart listener.
1062fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    mPermission = BluetoothDevice.ACCESS_REJECTED;
1063fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    if (intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)) {
1064fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        boolean result = mRemoteDevice.setMessageAccessPermission(
1065fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                BluetoothDevice.ACCESS_REJECTED);
1066fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        if (DEBUG) {
1067fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                            Log.d(TAG, "setMessageAccessPermission(ACCESS_REJECTED) result="
1068fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                                    + result);
1069fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                        }
1070fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee                    }
1071326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    sendConnectCancelMessage();
1072326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
1073fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala            } else if (action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
1074fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                if (DEBUG) Log.d(TAG, "Received ACTION_SDP_RECORD.");
1075bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
1076f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                if (VERBOSE) {
1077f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    Log.v(TAG, "Received UUID: " + uuid.toString());
1078f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    Log.v(TAG, "expected UUID: " +
1079f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                          BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS.toString());
1080f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                }
1081fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                if (uuid.equals(BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS)) {
1082bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mMnsRecord = intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
1083bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1);
1084f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    if (VERBOSE) {
1085f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                        Log.v(TAG, " -> MNS Record:" + mMnsRecord);
1086f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                        Log.v(TAG, " -> status: " + status);
1087f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    }
1088fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    if (mBluetoothMnsObexClient != null && !mSdpSearchInitiated) {
1089fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        mBluetoothMnsObexClient.setMnsRecord(mMnsRecord);
1090fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    }
1091fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    if (status != -1 && mMnsRecord != null) {
1092fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        for (int i = 0, c = mMasInstances.size(); i < c; i++) {
1093bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                mMasInstances.valueAt(i).setRemoteFeatureMask(
1094bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        mMnsRecord.getSupportedFeatures());
1095bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        }
1096bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    }
1097fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    if (mSdpSearchInitiated) {
1098fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        mSdpSearchInitiated = false; // done searching
1099fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                        sendConnectMessage(-1); // -1 indicates all MAS instances
1100fc8dfd1e037cda063919d9160c9cdb604b9adfefAshwini Munigala                    }
1101bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
11025a60e47497f21f64e6d79420dc4c56c1907df22akschulz            } else if (action.equals(ACTION_SHOW_MAPS_SETTINGS)) {
1103f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                if (VERBOSE) Log.v(TAG, "Received ACTION_SHOW_MAPS_SETTINGS.");
1104326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
11055a60e47497f21f64e6d79420dc4c56c1907df22akschulz                Intent in = new Intent(context, BluetoothMapSettings.class);
1106326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
1107326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                context.startActivity(in);
1108326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            } else if (action.equals(BluetoothMapContentObserver.ACTION_MESSAGE_SENT)) {
1109326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                BluetoothMapMasInstance masInst = null;
1110326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                int result = getResultCode();
1111326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                boolean handled = false;
11124d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                if(mSmsCapable && mMasInstances != null &&
11134d2c98fcf1abc4b07dc2d4601952f30f5d008470rongbo.x.chi                        (masInst = mMasInstances.get(MAS_ID_SMS_MMS)) != null) {
1114326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    intent.putExtra(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_RESULT, result);
1115326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    if(masInst.handleSmsSendIntent(context, intent)) {
1116326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        // The intent was handled by the mas instance it self
1117326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                        handled = true;
1118326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    }
1119326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                }
1120326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                if(handled == false)
1121326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                {
1122326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    /* We do not have a connection to a device, hence we need to move
1123326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                       the SMS to the correct folder. */
112460e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                    try {
112560e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                        BluetoothMapContentObserver
1126bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                            .actionMessageSentDisconnected(context, intent, result);
112760e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                    } catch(IllegalArgumentException e) {
112860e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                        return;
112960e306ba5c132d5408ccae3a290e7cace020a49fSeven Shen                    }
113070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                }
113143b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED) &&
1132326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    mIsWaitingAuthorization) {
113343b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
113443b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta
113543b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                if (mRemoteDevice == null || device == null) {
113643b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    Log.e(TAG, "Unexpected error!");
113743b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    return;
113843b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                }
113943b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta
1140f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                if (VERBOSE) Log.v(TAG,"ACL disconnected for " + device);
114143b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta
1142f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                if (mRemoteDevice.equals(device)) {
114343b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    // Send any pending timeout now, as ACL got disconnected.
114443b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    mSessionStatusHandler.removeMessages(USER_TIMEOUT);
114543b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta
114643b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    Intent timeoutIntent =
114743b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                            new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
114843b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    timeoutIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
114943b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    timeoutIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
115043b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                                           BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS);
115143b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                    sendBroadcast(timeoutIntent, BLUETOOTH_PERM);
1152326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                    mIsWaitingAuthorization = false;
1153f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    cancelUserTimeoutAlarm();
1154f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                    mSessionStatusHandler.obtainMessage(MSG_SERVERSESSION_CLOSE, -1, 0)
1155f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde                            .sendToTarget();
115643b941ed67f10876a3d730cc095ddb6589e9c1b6Hemant Gupta                }
115770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            }
115870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
115970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    };
116070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
116170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    //Binder object: Must be static class or memory leak may occur
116270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    /**
116370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz     * This class implements the IBluetoothMap interface - or actually it validates the
116470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz     * preconditions for calling the actual functionality in the MapService, and calls it.
116570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz     */
116670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private static class BluetoothMapBinder extends IBluetoothMap.Stub
116770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        implements IProfileServiceBinder {
116870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        private BluetoothMapService mService;
116970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
117070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        private BluetoothMapService getService() {
1171fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            if (!Utils.checkCaller()) {
117270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                Log.w(TAG,"MAP call not allowed for non-active user");
1173fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie                return null;
1174fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
1175fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
117670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (mService != null && mService.isAvailable()) {
1177bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                mService.enforceCallingOrSelfPermission(BLUETOOTH_PERM,"Need BLUETOOTH permission");
117870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz                return mService;
1179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
118070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return null;
1181fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
118370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        BluetoothMapBinder(BluetoothMapService service) {
118470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "BluetoothMapBinder()");
118570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            mService = service;
118670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
1187fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
118870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public boolean cleanup()  {
118970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            mService = null;
119070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return true;
1191fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
119370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public int getState() {
119470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "getState()");
119570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
119670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return BluetoothMap.STATE_DISCONNECTED;
119770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return getService().getState();
119870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
119970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
120070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public BluetoothDevice getClient() {
120170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "getClient()");
120270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
120370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return null;
1204f48c0b98b5d1823fbb0fc3e4eba7d5054d9385faCasper Bonde            if (VERBOSE) Log.v(TAG, "getClient() - returning " + service.getRemoteDevice());
120570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.getRemoteDevice();
120670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
120770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
120870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public boolean isConnected(BluetoothDevice device) {
120970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "isConnected()");
121070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
121170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return false;
1212bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return service.getState() == BluetoothMap.STATE_CONNECTED
1213bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    && service.getRemoteDevice().equals(device);
121470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
1215fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
121670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public boolean connect(BluetoothDevice device) {
121770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "connect()");
121870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
121970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return false;
1220fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            return false;
1221fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1222fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
122370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public boolean disconnect(BluetoothDevice device) {
122470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "disconnect()");
122570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
122670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return false;
122770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.disconnect(device);
122870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
1229fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
123070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public List<BluetoothDevice> getConnectedDevices() {
123170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "getConnectedDevices()");
123270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
123370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return new ArrayList<BluetoothDevice>(0);
123470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.getConnectedDevices();
123570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
1236fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
123770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
123870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "getDevicesMatchingConnectionStates()");
123970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
124070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return new ArrayList<BluetoothDevice>(0);
124170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.getDevicesMatchingConnectionStates(states);
124270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
124370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
124470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public int getConnectionState(BluetoothDevice device) {
124570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (VERBOSE) Log.v(TAG, "getConnectionState()");
124670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
124770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
124870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.getConnectionState(device);
124970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
125070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
125170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public boolean setPriority(BluetoothDevice device, int priority) {
125270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
125370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return false;
125470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.setPriority(device, priority);
125570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
125670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
125770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        public int getPriority(BluetoothDevice device) {
125870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            BluetoothMapService service = getService();
125970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
126070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            return service.getPriority(device);
1261fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
1262326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
1263838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood
1264838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    @Override
1265838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    public void dump(StringBuilder sb) {
1266838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        super.dump(sb);
1267838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mRemoteDevice: " + mRemoteDevice);
1268838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "sRemoteDeviceName: " + sRemoteDeviceName);
1269838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mState: " + mState);
1270838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mAppObserver: " + mAppObserver);
1271838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mIsWaitingAuthorization: " + mIsWaitingAuthorization);
1272838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mRemoveTimeoutMsg: " + mRemoveTimeoutMsg);
1273838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mPermission: " + mPermission);
1274838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mAccountChanged: " + mAccountChanged);
1275838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mBluetoothMnsObexClient: " + mBluetoothMnsObexClient);
1276838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mMasInstanceMap:");
12775a60e47497f21f64e6d79420dc4c56c1907df22akschulz        for (BluetoothMapAccountItem key : mMasInstanceMap.keySet()) {
1278838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood            println(sb, "  " + key + " : " + mMasInstanceMap.get(key));
1279838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
1280838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        println(sb, "mEnabledAccounts:");
12815a60e47497f21f64e6d79420dc4c56c1907df22akschulz        for (BluetoothMapAccountItem account : mEnabledAccounts) {
1282838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood            println(sb, "  " + account);
1283838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
1284838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    }
1285fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie}
1286