16c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/* 26c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Copyright (C) 2008 The Android Open Source Project 36c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * 46c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Licensed under the Apache License, Version 2.0 (the "License"); 56c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * you may not use this file except in compliance with the License. 66c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * You may obtain a copy of the License at 76c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * 86c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * http://www.apache.org/licenses/LICENSE-2.0 96c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * 106c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Unless required by applicable law or agreed to in writing, software 116c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * distributed under the License is distributed on an "AS IS" BASIS, 126c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * See the License for the specific language governing permissions and 146c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * limitations under the License. 156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 166c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiepackage com.android.bluetooth.hfp; 186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 19405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi Timport com.android.bluetooth.R; 20405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport com.android.internal.telephony.GsmAlphabet; 226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.BluetoothDevice; 2474ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.content.ContentResolver; 256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.content.Context; 266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.content.Intent; 276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.database.Cursor; 286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.net.Uri; 296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.provider.CallLog.Calls; 306c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.provider.ContactsContract.CommonDataKinds.Phone; 316c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.provider.ContactsContract.PhoneLookup; 326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.telephony.PhoneNumberUtils; 336c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.util.Log; 34343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastavaimport com.android.bluetooth.Utils; 35343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava 366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 376c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport java.util.HashMap; 386c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 396c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/** 406c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Helper for managing phonebook presentation over AT commands 416c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * @hide 426c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 436c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiepublic class AtPhonebook { 446c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String TAG = "BluetoothAtPhonebook"; 456c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final boolean DBG = false; 466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie /** The projection to use when querying the call log database in response 486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * to AT+CPBR for the MC, RC, and DC phone books (missed, received, and 496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * dialed calls respectively) 506c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 516c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String[] CALLS_PROJECTION = new String[] { 529674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner Calls._ID, Calls.NUMBER, Calls.NUMBER_PRESENTATION 536c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie }; 546c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 556c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie /** The projection to use when querying the contacts database in response 566c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * to AT+CPBR for the ME phonebook (saved phone numbers). 576c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 586c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String[] PHONES_PROJECTION = new String[] { 596c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie Phone._ID, Phone.DISPLAY_NAME, Phone.NUMBER, Phone.TYPE 606c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie }; 616c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie /** Android supports as many phonebook entries as the flash can hold, but 636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * BT periphals don't. Limit the number we'll report. */ 646c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final int MAX_PHONEBOOK_SIZE = 16384; 656c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 666c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String OUTGOING_CALL_WHERE = Calls.TYPE + "=" + Calls.OUTGOING_TYPE; 676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String INCOMING_CALL_WHERE = Calls.TYPE + "=" + Calls.INCOMING_TYPE; 686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String MISSED_CALL_WHERE = Calls.TYPE + "=" + Calls.MISSED_TYPE; 696c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String VISIBLE_PHONEBOOK_WHERE = Phone.IN_VISIBLE_GROUP + "=1"; 706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private class PhonebookResult { 726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public Cursor cursor; // result set of last query 736c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int numberColumn; 749674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner public int numberPresentationColumn; 756c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int typeColumn; 766c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int nameColumn; 776c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie }; 786c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc private Context mContext; 8074ae04c73312403e89db0f8e9bd9601d403b4783fredc private ContentResolver mContentResolver; 81405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T private HeadsetStateMachine mStateMachine; 826c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private String mCurrentPhonebook; 836c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private String mCharacterSet = "UTF-8"; 846c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private int mCpbrIndex1, mCpbrIndex2; 866c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private boolean mCheckingAccessPermission; 876c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // package and class name to which we send intent to check phone book access permission 896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings"; 906c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String ACCESS_AUTHORITY_CLASS = 916c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie "com.android.settings.bluetooth.BluetoothPermissionRequest"; 926c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 936c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 946c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private final HashMap<String, PhonebookResult> mPhonebooks = 956c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie new HashMap<String, PhonebookResult>(4); 966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 97405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T final int TYPE_UNKNOWN = -1; 98405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T final int TYPE_READ = 0; 99405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T final int TYPE_SET = 1; 100405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T final int TYPE_TEST = 2; 101405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 102405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T public AtPhonebook(Context context, HeadsetStateMachine headsetState) { 1036c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mContext = context; 10474ae04c73312403e89db0f8e9bd9601d403b4783fredc mContentResolver = context.getContentResolver(); 105405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mStateMachine = headsetState; 1066c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mPhonebooks.put("DC", new PhonebookResult()); // dialled calls 1076c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mPhonebooks.put("RC", new PhonebookResult()); // received calls 1086c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mPhonebooks.put("MC", new PhonebookResult()); // missed calls 1096c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mPhonebooks.put("ME", new PhonebookResult()); // mobile phonebook 1106c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1116c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCurrentPhonebook = "ME"; // default to mobile phonebook 1126c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1136c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCpbrIndex1 = mCpbrIndex2 = -1; 1146c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCheckingAccessPermission = false; 1156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1166c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 11774ae04c73312403e89db0f8e9bd9601d403b4783fredc public void cleanup() { 11874ae04c73312403e89db0f8e9bd9601d403b4783fredc mPhonebooks.clear(); 11974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 12074ae04c73312403e89db0f8e9bd9601d403b4783fredc 1216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie /** Returns the last dialled number, or null if no numbers have been called */ 1226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public String getLastDialledNumber() { 1236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie String[] projection = {Calls.NUMBER}; 12474ae04c73312403e89db0f8e9bd9601d403b4783fredc Cursor cursor = mContentResolver.query(Calls.CONTENT_URI, projection, 1256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie Calls.TYPE + "=" + Calls.OUTGOING_TYPE, null, Calls.DEFAULT_SORT_ORDER + 1266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie " LIMIT 1"); 1276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (cursor == null) return null; 1286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (cursor.getCount() < 1) { 1306c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie cursor.close(); 1316c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return null; 1326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1336c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie cursor.moveToNext(); 1346c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie int column = cursor.getColumnIndexOrThrow(Calls.NUMBER); 1356c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie String number = cursor.getString(column); 1366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie cursor.close(); 1376c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return number; 1386c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1396c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 140405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T public boolean getCheckingAccessPermission() { 141405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T return mCheckingAccessPermission; 142405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 143405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 144fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee public void setCheckingAccessPermission(boolean checkingAccessPermission) { 145fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee mCheckingAccessPermission = checkingAccessPermission; 146405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 147405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 148405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T public void setCpbrIndex(int cpbrIndex) { 149405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCpbrIndex1 = mCpbrIndex2 = cpbrIndex; 150405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 151405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 152343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava private byte[] getByteAddress(BluetoothDevice device) { 153343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava return Utils.getBytesFromAddress(device.getAddress()); 154343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava } 155343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava 156343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava public void handleCscsCommand(String atString, int type, BluetoothDevice device) 157405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T { 158405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCscsCommand - atString = " +atString); 159405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Select Character Set 160405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; 161405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandErrorCode = -1; 162405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String atCommandResponse = null; 163405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T switch (type) { 164405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_READ: // Read 165405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCscsCommand - Read Command"); 166405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = "+CSCS: \"" + mCharacterSet + "\""; 167405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 168405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 169405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_TEST: // Test 170405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCscsCommand - Test Command"); 171405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = ( "+CSCS: (\"UTF-8\",\"IRA\",\"GSM\")"); 172405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 173405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 174405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_SET: // Set 175405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCscsCommand - Set Command"); 176405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String[] args = atString.split("="); 177405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (args.length < 2 || !(args[1] instanceof String)) { 178343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, 179343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava atCommandErrorCode, getByteAddress(device)); 180405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 181405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 182405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String characterSet = ((atString.split("="))[1]); 183405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T characterSet = characterSet.replace("\"", ""); 184405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (characterSet.equals("GSM") || characterSet.equals("IRA") || 185405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T characterSet.equals("UTF-8") || characterSet.equals("UTF8")) { 186405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCharacterSet = characterSet; 187405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 188405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } else { 189405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; 190405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 191405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 192405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_UNKNOWN: 193405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T default: 194405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCscsCommand - Invalid chars"); 195405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; 1966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 197405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (atCommandResponse != null) 198343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseStringNative(atCommandResponse, getByteAddress(device)); 199343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 200343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(device)); 201405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 2026c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 203343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava public void handleCpbsCommand(String atString, int type, BluetoothDevice device) { 204405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Select PhoneBook memory Storage 205405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbsCommand - atString = " +atString); 206405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; 207405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandErrorCode = -1; 208405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String atCommandResponse = null; 209405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T switch (type) { 210405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_READ: // Read 211405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbsCommand - read command"); 212405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Return current size and max size 213405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if ("SM".equals(mCurrentPhonebook)) { 214405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = "+CPBS: \"SM\",0," + getMaxPhoneBookSize(0); 215405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 216405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 217405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 218405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); 219405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (pbr == null) { 220405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; 221405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 2226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 223405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int size = pbr.cursor.getCount(); 224405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = "+CPBS: \"" + mCurrentPhonebook + "\"," + size + "," + getMaxPhoneBookSize(size); 22515d36984a79d6e35c659edb0efdf929f0b526bd5Fred pbr.cursor.close(); 22615d36984a79d6e35c659edb0efdf929f0b526bd5Fred pbr.cursor = null; 227405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 228405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 229405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_TEST: // Test 230405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbsCommand - test command"); 231405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = ("+CPBS: (\"ME\",\"SM\",\"DC\",\"RC\",\"MC\")"); 232405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 233405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 234405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_SET: // Set 235405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbsCommand - set command"); 236405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String[] args = atString.split("="); 237405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Select phonebook memory 238405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (args.length < 2 || !(args[1] instanceof String)) { 239d1e5ee9cd1c68ad8eeca61700fe56638d7f3edd4Nigel Hannam atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; 240405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 241405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 242405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String pb = ((String)args[1]).trim(); 243405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T while (pb.endsWith("\"")) pb = pb.substring(0, pb.length() - 1); 244405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T while (pb.startsWith("\"")) pb = pb.substring(1, pb.length()); 245405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (getPhonebookResult(pb, false) == null && !"SM".equals(pb)) { 246405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (DBG) log("Dont know phonebook: '" + pb + "'"); 247405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; 248405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 249405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 250405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCurrentPhonebook = pb; 251405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 252405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 253405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_UNKNOWN: 254405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T default: 255405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbsCommand - invalid chars"); 256405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; 257405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 258405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (atCommandResponse != null) 259343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseStringNative(atCommandResponse, getByteAddress(device)); 260343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 261343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(device)); 262405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 2636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 264405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T public void handleCpbrCommand(String atString, int type, BluetoothDevice remoteDevice) { 265405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbrCommand - atString = " +atString); 266405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; 267405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandErrorCode = -1; 268405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String atCommandResponse = null; 269405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T switch (type) { 270405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_TEST: // Test 271405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T /* Ideally we should return the maximum range of valid index's 272405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T * for the selected phone book, but this causes problems for the 273405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T * Parrot CK3300. So instead send just the range of currently 274405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T * valid index's. 275405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T */ 276405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbrCommand - test command"); 277405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int size; 278405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if ("SM".equals(mCurrentPhonebook)) { 279405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T size = 0; 280405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } else { 281405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); //false); 282405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (pbr == null) { 283405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; 284343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, 285343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava atCommandErrorCode, getByteAddress(remoteDevice)); 286405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 287405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 288405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T size = pbr.cursor.getCount(); 289405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbrCommand - size = "+size); 29015d36984a79d6e35c659edb0efdf929f0b526bd5Fred pbr.cursor.close(); 29115d36984a79d6e35c659edb0efdf929f0b526bd5Fred pbr.cursor = null; 292405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 293405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (size == 0) { 294405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T /* Sending "+CPBR: (1-0)" can confused some carkits, send "1-1" * instead */ 295405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T size = 1; 296405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 297405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = "+CPBR: (1-" + size + "),30,30"; 298405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 299405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (atCommandResponse != null) 300343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseStringNative(atCommandResponse, 301343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(remoteDevice)); 302343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 303343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(remoteDevice)); 304405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 305405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Read PhoneBook Entries 306405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_READ: 307405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T case TYPE_SET: // Set & read 308405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Phone Book Read Request 309405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // AT+CPBR=<index1>[,<index2>] 310405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("handleCpbrCommand - set/read command"); 311405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (mCpbrIndex1 != -1) { 312405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T /* handling a CPBR at the moment, reject this CPBR command */ 313405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; 314343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 315343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(remoteDevice)); 316405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 317405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 318405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T // Parse indexes 319405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int index1; 320405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int index2; 321405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if ((atString.split("=")).length < 2) { 322343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 323343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(remoteDevice)); 324405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 325405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 326405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String atCommand = (atString.split("="))[1]; 327405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String[] indices = atCommand.split(","); 328405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T for(int i = 0; i < indices.length; i++) 329be38be94c0a2faf3802b596be5b3ab568d6d85a4zzy //replace AT command separator ';' from the index if any 330be38be94c0a2faf3802b596be5b3ab568d6d85a4zzy indices[i] = indices[i].replace(';', ' ').trim(); 331405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T try { 332405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T index1 = Integer.parseInt(indices[0]); 333405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T if (indices.length == 1) 334405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T index2 = index1; 335405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T else 336405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T index2 = Integer.parseInt(indices[1]); 337405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 338405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T catch (Exception e) { 339be38be94c0a2faf3802b596be5b3ab568d6d85a4zzy log("handleCpbrCommand - exception - invalid chars: " + e.toString()); 340405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; 341343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 342343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(remoteDevice)); 343405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 344405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 345405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCpbrIndex1 = index1; 346405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCpbrIndex2 = index2; 347405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCheckingAccessPermission = true; 348405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 349fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee int permission = checkAccessPermission(remoteDevice); 350fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee if (permission == BluetoothDevice.ACCESS_ALLOWED) { 351405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCheckingAccessPermission = false; 352343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava atCommandResult = processCpbrCommand(remoteDevice); 353405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T mCpbrIndex1 = mCpbrIndex2 = -1; 354343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 355343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava getByteAddress(remoteDevice)); 356405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 357fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee } else if (permission == BluetoothDevice.ACCESS_REJECTED) { 358fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee mCheckingAccessPermission = false; 359fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee mCpbrIndex1 = mCpbrIndex2 = -1; 360fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee mStateMachine.atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_ERROR, 361fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee BluetoothCmeError.AG_FAILURE, getByteAddress(remoteDevice)); 362405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 363fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee // If checkAccessPermission(remoteDevice) has returned 364fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee // BluetoothDevice.ACCESS_UNKNOWN, we will continue the process in 365fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee // HeadsetStateMachine.handleAccessPermissionResult(Intent) once HeadsetService 366fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee // receives BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY from Settings app. 367405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T break; 368fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee case TYPE_UNKNOWN: 369fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee default: 370fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee log("handleCpbrCommand - invalid chars"); 371fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; 372fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode, 373fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee getByteAddress(remoteDevice)); 3746c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3756c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3766c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 3776c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie /** Get the most recent result for the given phone book, 3786c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * with the cursor ready to go. 3796c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * If force then re-query that phonebook 3806c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Returns null if the cursor is not ready 3816c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 3826c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private synchronized PhonebookResult getPhonebookResult(String pb, boolean force) { 3836c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pb == null) { 3846c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return null; 3856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3866c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie PhonebookResult pbr = mPhonebooks.get(pb); 3876c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr == null) { 3886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr = new PhonebookResult(); 3896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3906c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (force || pbr.cursor == null) { 3916c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (!queryPhonebook(pb, pbr)) { 3926c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return null; 3936c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3946c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3956c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 3966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return pbr; 3976c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3986c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 3996c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private synchronized boolean queryPhonebook(String pb, PhonebookResult pbr) { 4006c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie String where; 4016c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie boolean ancillaryPhonebook = true; 4026c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4036c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pb.equals("ME")) { 4046c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie ancillaryPhonebook = false; 4056c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie where = VISIBLE_PHONEBOOK_WHERE; 4066c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } else if (pb.equals("DC")) { 4076c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie where = OUTGOING_CALL_WHERE; 4086c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } else if (pb.equals("RC")) { 4096c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie where = INCOMING_CALL_WHERE; 4106c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } else if (pb.equals("MC")) { 4116c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie where = MISSED_CALL_WHERE; 4126c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } else { 4136c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return false; 4146c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4166c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr.cursor != null) { 4176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.cursor.close(); 4186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.cursor = null; 4196c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4206c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (ancillaryPhonebook) { 42274ae04c73312403e89db0f8e9bd9601d403b4783fredc pbr.cursor = mContentResolver.query( 4236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie Calls.CONTENT_URI, CALLS_PROJECTION, where, null, 4246c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie Calls.DEFAULT_SORT_ORDER + " LIMIT " + MAX_PHONEBOOK_SIZE); 4256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr.cursor == null) return false; 4266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.numberColumn = pbr.cursor.getColumnIndexOrThrow(Calls.NUMBER); 4289674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner pbr.numberPresentationColumn = 4299674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner pbr.cursor.getColumnIndexOrThrow(Calls.NUMBER_PRESENTATION); 4306c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.typeColumn = -1; 4316c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.nameColumn = -1; 4326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } else { 43374ae04c73312403e89db0f8e9bd9601d403b4783fredc pbr.cursor = mContentResolver.query(Phone.CONTENT_URI, PHONES_PROJECTION, 4346c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie where, null, Phone.NUMBER + " LIMIT " + MAX_PHONEBOOK_SIZE); 4356c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr.cursor == null) return false; 4366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4376c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.numberColumn = pbr.cursor.getColumnIndex(Phone.NUMBER); 4389674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner pbr.numberPresentationColumn = -1; 4396c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.typeColumn = pbr.cursor.getColumnIndex(Phone.TYPE); 4406c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.nameColumn = pbr.cursor.getColumnIndex(Phone.DISPLAY_NAME); 4416c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4426c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie Log.i(TAG, "Refreshed phonebook " + pb + " with " + pbr.cursor.getCount() + " results"); 4436c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return true; 4446c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4456c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie synchronized void resetAtState() { 4476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCharacterSet = "UTF-8"; 4486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCpbrIndex1 = mCpbrIndex2 = -1; 4496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCheckingAccessPermission = false; 4506c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4516c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private synchronized int getMaxPhoneBookSize(int currSize) { 4536c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // some car kits ignore the current size and request max phone book 4546c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // size entries. Thus, it takes a long time to transfer all the 4556c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // entries. Use a heuristic to calculate the max phone book size 4566c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // considering future expansion. 4576c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // maxSize = currSize + currSize / 2 rounded up to nearest power of 2 4586c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // If currSize < 100, use 100 as the currSize 4596c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4606c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie int maxSize = (currSize < 100) ? 100 : currSize; 4616c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie maxSize += maxSize / 2; 4626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return roundUpToPowerOfTwo(maxSize); 4636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4646c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4656c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private int roundUpToPowerOfTwo(int x) { 4666c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie x |= x >> 1; 4676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie x |= x >> 2; 4686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie x |= x >> 4; 4696c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie x |= x >> 8; 4706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie x |= x >> 16; 4716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return x + 1; 4726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4736c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4746c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // process CPBR command after permission check 475343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava /*package*/ int processCpbrCommand(BluetoothDevice device) 4766c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie { 477405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("processCpbrCommand"); 478405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; 479405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T int atCommandErrorCode = -1; 480405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String atCommandResponse = null; 481405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T StringBuilder response = new StringBuilder(); 482405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T String record; 483405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 4846c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // Shortcut SM phonebook 4856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if ("SM".equals(mCurrentPhonebook)) { 486405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 487405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T return atCommandResult; 4886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4906c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // Check phonebook 491405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); //false); 4926c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr == null) { 493405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; 494405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T return atCommandResult; 4956c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 4966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 4976c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // More sanity checks 4986c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // Send OK instead of ERROR if these checks fail. 4996c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // When we send error, certain kits like BMW disconnect the 5006c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // Handsfree connection. 5016c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr.cursor.getCount() == 0 || mCpbrIndex1 <= 0 || mCpbrIndex2 < mCpbrIndex1 || 5026c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie mCpbrIndex2 > pbr.cursor.getCount() || mCpbrIndex1 > pbr.cursor.getCount()) { 503405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 504405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T return atCommandResult; 5056c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5066c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 5076c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // Process 508405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; 5096c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie int errorDetected = -1; // no error 5106c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie pbr.cursor.moveToPosition(mCpbrIndex1 - 1); 511405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("mCpbrIndex1 = "+mCpbrIndex1+ " and mCpbrIndex2 = "+mCpbrIndex2); 5126c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie for (int index = mCpbrIndex1; index <= mCpbrIndex2; index++) { 5136c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie String number = pbr.cursor.getString(pbr.numberColumn); 5146c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie String name = null; 5156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie int type = -1; 51609b09c15dcd853d452b24d46a3c81ca63fa090eaMatthew Xie if (pbr.nameColumn == -1 && number != null && number.length() > 0) { 5176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // try caller id lookup 5186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // TODO: This code is horribly inefficient. I saw it 5196c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // take 7 seconds to process 100 missed calls. 52074ae04c73312403e89db0f8e9bd9601d403b4783fredc Cursor c = mContentResolver. 5216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number), 5226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE}, 5236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie null, null, null); 5246c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (c != null) { 5256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (c.moveToFirst()) { 5266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie name = c.getString(0); 5276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie type = c.getInt(1); 5286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie c.close(); 5306c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5316c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (DBG && name == null) log("Caller ID lookup failed for " + number); 5326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 533abf19e783556a93cfdd33468454a309ed347bfc4Zhihai Xu } else if (pbr.nameColumn != -1) { 5346c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie name = pbr.cursor.getString(pbr.nameColumn); 535abf19e783556a93cfdd33468454a309ed347bfc4Zhihai Xu } else { 536abf19e783556a93cfdd33468454a309ed347bfc4Zhihai Xu log("processCpbrCommand: empty name and number"); 5376c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5386c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (name == null) name = ""; 5396c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie name = name.trim(); 5406c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (name.length() > 28) name = name.substring(0, 28); 5416c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 5426c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (pbr.typeColumn != -1) { 5436c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie type = pbr.cursor.getInt(pbr.typeColumn); 5446c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie name = name + "/" + getPhoneType(type); 5456c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 5476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (number == null) number = ""; 5486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie int regionType = PhoneNumberUtils.toaFromString(number); 5496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 5506c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie number = number.trim(); 5516c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie number = PhoneNumberUtils.stripSeparators(number); 5526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (number.length() > 30) number = number.substring(0, 30); 5539674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner int numberPresentation = Calls.PRESENTATION_ALLOWED; 5549674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner if (pbr.numberPresentationColumn != -1) { 5559674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner numberPresentation = pbr.cursor.getInt(pbr.numberPresentationColumn); 5569674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner } 5579674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner if (numberPresentation != Calls.PRESENTATION_ALLOWED) { 5586c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie number = ""; 5599674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner // TODO: there are 3 types of numbers should have resource 5609674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner // strings for: unknown, private, and payphone 561405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T name = mContext.getString(R.string.unknownNumber); 5626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 5646c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // TODO(): Handle IRA commands. It's basically 5656c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie // a 7 bit ASCII character set. 5666c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (!name.equals("") && mCharacterSet.equals("GSM")) { 5676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie byte[] nameByte = GsmAlphabet.stringToGsm8BitPacked(name); 5686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (nameByte == null) { 569405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T name = mContext.getString(R.string.unknownNumber); 5706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } else { 5716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie name = new String(nameByte); 5726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5736c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5746c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 575405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T record = "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + name + "\""; 576405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T record = record + "\r\n\r\n"; 577405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T atCommandResponse = record; 578405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("processCpbrCommand - atCommandResponse = "+atCommandResponse); 579343b96e3995da4038b614384dcdad8a6494b4bc4Nitin Srivastava mStateMachine.atResponseStringNative(atCommandResponse, getByteAddress(device)); 5806c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie if (!pbr.cursor.moveToNext()) { 5816c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie break; 5826c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 5836c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 58415d36984a79d6e35c659edb0efdf929f0b526bd5Fred if(pbr != null && pbr.cursor != null) { 58515d36984a79d6e35c659edb0efdf929f0b526bd5Fred pbr.cursor.close(); 58615d36984a79d6e35c659edb0efdf929f0b526bd5Fred pbr.cursor = null; 58715d36984a79d6e35c659edb0efdf929f0b526bd5Fred } 588405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T return atCommandResult; 589405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 590405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 591fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee /** 592fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee * Checks if the remote device has premission to read our phone book. 593fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee * If the return value is {@link BluetoothDevice#ACCESS_UNKNOWN}, it means this method has sent 594fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee * an Intent to Settings application to ask user preference. 595fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee * 596fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee * @return {@link BluetoothDevice#ACCESS_UNKNOWN}, {@link BluetoothDevice#ACCESS_ALLOWED} or 597fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee * {@link BluetoothDevice#ACCESS_REJECTED}. 598fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee */ 599fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee private int checkAccessPermission(BluetoothDevice remoteDevice) { 600405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T log("checkAccessPermission"); 601fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee int permission = remoteDevice.getPhonebookAccessPermission(); 602fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee 603fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee if (permission == BluetoothDevice.ACCESS_UNKNOWN) { 604fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee log("checkAccessPermission - ACTION_CONNECTION_ACCESS_REQUEST"); 605fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST); 606fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS); 607fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, 608fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); 609fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee intent.putExtra(BluetoothDevice.EXTRA_DEVICE, remoteDevice); 610fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee // Leave EXTRA_PACKAGE_NAME and EXTRA_CLASS_NAME field empty. 611fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee // BluetoothHandsfree's broadcast receiver is anonymous, cannot be targeted. 612fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee mContext.sendOrderedBroadcast(intent, BLUETOOTH_ADMIN_PERM); 613405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T } 614405b6148a168c05f9c9eac6a80db68b9a58392e2Sreenidhi T 615fc9bed1b79edf77082f5baa21aa68d791a102ea4Edward Jee return permission; 6166c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 6176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 6186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static String getPhoneType(int type) { 6196c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie switch (type) { 6206c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_HOME: 6216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return "H"; 6226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_MOBILE: 6236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return "M"; 6246c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_WORK: 6256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return "W"; 6266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_FAX_HOME: 6276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_FAX_WORK: 6286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return "F"; 6296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_OTHER: 6306c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie case Phone.TYPE_CUSTOM: 6316c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie default: 6326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return "O"; 6336c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 6346c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 6356c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 6366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static void log(String msg) { 6376c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie Log.d(TAG, msg); 6386c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 6396c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie} 640