191197049c458f07092b31501d2ed512180b13d58Chiao Cheng/* 291197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Copyright (C) 2006 The Android Open Source Project 391197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 591197049c458f07092b31501d2ed512180b13d58Chiao Cheng * you may not use this file except in compliance with the License. 691197049c458f07092b31501d2ed512180b13d58Chiao Cheng * You may obtain a copy of the License at 791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 1091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Unless required by applicable law or agreed to in writing, software 1191197049c458f07092b31501d2ed512180b13d58Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 1291197049c458f07092b31501d2ed512180b13d58Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391197049c458f07092b31501d2ed512180b13d58Chiao Cheng * See the License for the specific language governing permissions and 1491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * limitations under the License. 1591197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 1691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 1791197049c458f07092b31501d2ed512180b13d58Chiao Chengpackage com.android.dialer; 1891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 1991197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.app.AlertDialog; 2091197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.app.KeyguardManager; 2191197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.app.ProgressDialog; 221d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hambyimport android.content.ActivityNotFoundException; 2391197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.content.ContentResolver; 2491197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.content.Context; 2591197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.content.DialogInterface; 2691197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.content.Intent; 2791197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.database.Cursor; 2891197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.net.Uri; 2991197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.os.Looper; 30f4f47665942b34a1bab272b84f223bb06825a57fJeff Sharkeyimport android.provider.Settings; 319dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunnimport android.telecom.TelecomManager; 3291197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.telephony.PhoneNumberUtils; 3391197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.telephony.TelephonyManager; 3491197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.util.Log; 3591197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.view.WindowManager; 3691197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.widget.EditText; 3791197049c458f07092b31501d2ed512180b13d58Chiao Chengimport android.widget.Toast; 3891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 39ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shraunerimport com.android.common.io.MoreCloseables; 4007af764827a7d6d426f6097d3e769084968f84fdChiao Chengimport com.android.contacts.common.database.NoNullCursorAsyncQueryHandler; 4191197049c458f07092b31501d2ed512180b13d58Chiao Cheng 4291197049c458f07092b31501d2ed512180b13d58Chiao Cheng/** 4391197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Helper class to listen for some magic character sequences 4491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * that are handled specially by the dialer. 4591197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 4691197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Note the Phone app also handles these sequences too (in a couple of 471d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby * relatively obscure places in the UI), so there's a separate version of 4891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * this class under apps/Phone. 4991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 5091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * TODO: there's lots of duplicated code between this class and the 5191197049c458f07092b31501d2ed512180b13d58Chiao Cheng * corresponding class under apps/Phone. Let's figure out a way to 5291197049c458f07092b31501d2ed512180b13d58Chiao Cheng * unify these two classes (in the framework? in a common shared library?) 5391197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 5491197049c458f07092b31501d2ed512180b13d58Chiao Chengpublic class SpecialCharSequenceMgr { 5591197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static final String TAG = "SpecialCharSequenceMgr"; 561d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby 57f90dadaf0e46463e4ff24ad4267981b7196fe96fYorke Lee private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE"; 5891197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static final String MMI_IMEI_DISPLAY = "*#06#"; 591d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby private static final String MMI_REGULATORY_INFO_DISPLAY = "*#07#"; 6091197049c458f07092b31501d2ed512180b13d58Chiao Cheng 6191197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 6291197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Remembers the previous {@link QueryHandler} and cancel the operation when needed, to 6391197049c458f07092b31501d2ed512180b13d58Chiao Cheng * prevent possible crash. 6491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 6591197049c458f07092b31501d2ed512180b13d58Chiao Cheng * QueryHandler may call {@link ProgressDialog#dismiss()} when the screen is already gone, 6691197049c458f07092b31501d2ed512180b13d58Chiao Cheng * which will cause the app crash. This variable enables the class to prevent the crash 6791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * on {@link #cleanup()}. 6891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 6991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * TODO: Remove this and replace it (and {@link #cleanup()}) with better implementation. 701d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby * One complication is that we have SpecialCharSequenceMgr in Phone package too, which has 7191197049c458f07092b31501d2ed512180b13d58Chiao Cheng * *slightly* different implementation. Note that Phone package doesn't have this problem, 7291197049c458f07092b31501d2ed512180b13d58Chiao Cheng * so the class on Phone side doesn't have this functionality. 7391197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Fundamental fix would be to have one shared implementation and resolve this corner case more 7491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * gracefully. 7591197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 7691197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static QueryHandler sPreviousAdnQueryHandler; 7791197049c458f07092b31501d2ed512180b13d58Chiao Cheng 7891197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** This class is never instantiated. */ 7991197049c458f07092b31501d2ed512180b13d58Chiao Cheng private SpecialCharSequenceMgr() { 8091197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 8191197049c458f07092b31501d2ed512180b13d58Chiao Cheng 8291197049c458f07092b31501d2ed512180b13d58Chiao Cheng public static boolean handleChars(Context context, String input, EditText textField) { 8391197049c458f07092b31501d2ed512180b13d58Chiao Cheng return handleChars(context, input, false, textField); 8491197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 8591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 8691197049c458f07092b31501d2ed512180b13d58Chiao Cheng static boolean handleChars(Context context, String input) { 8791197049c458f07092b31501d2ed512180b13d58Chiao Cheng return handleChars(context, input, false, null); 8891197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 8991197049c458f07092b31501d2ed512180b13d58Chiao Cheng 9091197049c458f07092b31501d2ed512180b13d58Chiao Cheng static boolean handleChars(Context context, String input, boolean useSystemWindow, 9191197049c458f07092b31501d2ed512180b13d58Chiao Cheng EditText textField) { 9291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 9391197049c458f07092b31501d2ed512180b13d58Chiao Cheng //get rid of the separators so that the string gets parsed correctly 9491197049c458f07092b31501d2ed512180b13d58Chiao Cheng String dialString = PhoneNumberUtils.stripSeparators(input); 9591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 9691197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (handleIMEIDisplay(context, dialString, useSystemWindow) 971d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby || handleRegulatoryInfoDisplay(context, dialString) 9891197049c458f07092b31501d2ed512180b13d58Chiao Cheng || handlePinEntry(context, dialString) 9991197049c458f07092b31501d2ed512180b13d58Chiao Cheng || handleAdnEntry(context, dialString, textField) 10091197049c458f07092b31501d2ed512180b13d58Chiao Cheng || handleSecretCode(context, dialString)) { 10191197049c458f07092b31501d2ed512180b13d58Chiao Cheng return true; 10291197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 10391197049c458f07092b31501d2ed512180b13d58Chiao Cheng 10491197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 10591197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 10691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 10791197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 10891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Cleanup everything around this class. Must be run inside the main thread. 10991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 11091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * This should be called when the screen becomes background. 11191197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 11291197049c458f07092b31501d2ed512180b13d58Chiao Cheng public static void cleanup() { 11391197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (Looper.myLooper() != Looper.getMainLooper()) { 11491197049c458f07092b31501d2ed512180b13d58Chiao Cheng Log.wtf(TAG, "cleanup() is called outside the main thread"); 11591197049c458f07092b31501d2ed512180b13d58Chiao Cheng return; 11691197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 11791197049c458f07092b31501d2ed512180b13d58Chiao Cheng 11891197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (sPreviousAdnQueryHandler != null) { 11991197049c458f07092b31501d2ed512180b13d58Chiao Cheng sPreviousAdnQueryHandler.cancel(); 12091197049c458f07092b31501d2ed512180b13d58Chiao Cheng sPreviousAdnQueryHandler = null; 12191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 12291197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 12391197049c458f07092b31501d2ed512180b13d58Chiao Cheng 12491197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 12591197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Handles secret codes to launch arbitrary activities in the form of *#*#<code>#*#*. 12691197049c458f07092b31501d2ed512180b13d58Chiao Cheng * If a secret code is encountered an Intent is started with the android_secret_code://<code> 12791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * URI. 12891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 12991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * @param context the context to use 13091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * @param input the text to check for a secret code in 13191197049c458f07092b31501d2ed512180b13d58Chiao Cheng * @return true if a secret code was encountered 13291197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 13391197049c458f07092b31501d2ed512180b13d58Chiao Cheng static boolean handleSecretCode(Context context, String input) { 13491197049c458f07092b31501d2ed512180b13d58Chiao Cheng // Secret codes are in the form *#*#<code>#*#* 13591197049c458f07092b31501d2ed512180b13d58Chiao Cheng int len = input.length(); 13691197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) { 137f90dadaf0e46463e4ff24ad4267981b7196fe96fYorke Lee final Intent intent = new Intent(SECRET_CODE_ACTION, 13891197049c458f07092b31501d2ed512180b13d58Chiao Cheng Uri.parse("android_secret_code://" + input.substring(4, len - 4))); 13991197049c458f07092b31501d2ed512180b13d58Chiao Cheng context.sendBroadcast(intent); 14091197049c458f07092b31501d2ed512180b13d58Chiao Cheng return true; 14191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 14291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 14391197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 14491197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 14591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 14691197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 14791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Handle ADN requests by filling in the SIM contact number into the requested 14891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * EditText. 14991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 15091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * This code works alongside the Asynchronous query handler {@link QueryHandler} 15191197049c458f07092b31501d2ed512180b13d58Chiao Cheng * and query cancel handler implemented in {@link SimContactQueryCookie}. 15291197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 15391197049c458f07092b31501d2ed512180b13d58Chiao Cheng static boolean handleAdnEntry(Context context, String input, EditText textField) { 15491197049c458f07092b31501d2ed512180b13d58Chiao Cheng /* ADN entries are of the form "N(N)(N)#" */ 15591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 15691197049c458f07092b31501d2ed512180b13d58Chiao Cheng TelephonyManager telephonyManager = 15791197049c458f07092b31501d2ed512180b13d58Chiao Cheng (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 15891197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (telephonyManager == null 15962280c72fd651b00dd5499f4c3b32f30be57ce0dYorke Lee || telephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) { 16091197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 16191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 16291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 16391197049c458f07092b31501d2ed512180b13d58Chiao Cheng // if the phone is keyguard-restricted, then just ignore this 16491197049c458f07092b31501d2ed512180b13d58Chiao Cheng // input. We want to make sure that sim card contacts are NOT 16591197049c458f07092b31501d2ed512180b13d58Chiao Cheng // exposed unless the phone is unlocked, and this code can be 16691197049c458f07092b31501d2ed512180b13d58Chiao Cheng // accessed from the emergency dialer. 16791197049c458f07092b31501d2ed512180b13d58Chiao Cheng KeyguardManager keyguardManager = 16891197049c458f07092b31501d2ed512180b13d58Chiao Cheng (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); 16991197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (keyguardManager.inKeyguardRestrictedInputMode()) { 17091197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 17191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 17291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 17391197049c458f07092b31501d2ed512180b13d58Chiao Cheng int len = input.length(); 17491197049c458f07092b31501d2ed512180b13d58Chiao Cheng if ((len > 1) && (len < 5) && (input.endsWith("#"))) { 17591197049c458f07092b31501d2ed512180b13d58Chiao Cheng try { 17691197049c458f07092b31501d2ed512180b13d58Chiao Cheng // get the ordinal number of the sim contact 17791197049c458f07092b31501d2ed512180b13d58Chiao Cheng int index = Integer.parseInt(input.substring(0, len-1)); 17891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 17991197049c458f07092b31501d2ed512180b13d58Chiao Cheng // The original code that navigated to a SIM Contacts list view did not 18091197049c458f07092b31501d2ed512180b13d58Chiao Cheng // highlight the requested contact correctly, a requirement for PTCRB 18191197049c458f07092b31501d2ed512180b13d58Chiao Cheng // certification. This behaviour is consistent with the UI paradigm 18291197049c458f07092b31501d2ed512180b13d58Chiao Cheng // for touch-enabled lists, so it does not make sense to try to work 18391197049c458f07092b31501d2ed512180b13d58Chiao Cheng // around it. Instead we fill in the the requested phone number into 18491197049c458f07092b31501d2ed512180b13d58Chiao Cheng // the dialer text field. 18591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 18691197049c458f07092b31501d2ed512180b13d58Chiao Cheng // create the async query handler 18791197049c458f07092b31501d2ed512180b13d58Chiao Cheng QueryHandler handler = new QueryHandler (context.getContentResolver()); 18891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 18991197049c458f07092b31501d2ed512180b13d58Chiao Cheng // create the cookie object 19091197049c458f07092b31501d2ed512180b13d58Chiao Cheng SimContactQueryCookie sc = new SimContactQueryCookie(index - 1, handler, 19191197049c458f07092b31501d2ed512180b13d58Chiao Cheng ADN_QUERY_TOKEN); 19291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 19391197049c458f07092b31501d2ed512180b13d58Chiao Cheng // setup the cookie fields 19491197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.contactNum = index - 1; 19591197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.setTextField(textField); 19691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 19791197049c458f07092b31501d2ed512180b13d58Chiao Cheng // create the progress dialog 19891197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog = new ProgressDialog(context); 19991197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.setTitle(R.string.simContacts_title); 20091197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.setMessage(context.getText(R.string.simContacts_emptyLoading)); 20191197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.setIndeterminate(true); 20291197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.setCancelable(true); 20391197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.setOnCancelListener(sc); 20491197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.getWindow().addFlags( 20591197049c458f07092b31501d2ed512180b13d58Chiao Cheng WindowManager.LayoutParams.FLAG_BLUR_BEHIND); 20691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 20791197049c458f07092b31501d2ed512180b13d58Chiao Cheng // display the progress dialog 20891197049c458f07092b31501d2ed512180b13d58Chiao Cheng sc.progressDialog.show(); 20991197049c458f07092b31501d2ed512180b13d58Chiao Cheng 21091197049c458f07092b31501d2ed512180b13d58Chiao Cheng // run the query. 21191197049c458f07092b31501d2ed512180b13d58Chiao Cheng handler.startQuery(ADN_QUERY_TOKEN, sc, Uri.parse("content://icc/adn"), 21291197049c458f07092b31501d2ed512180b13d58Chiao Cheng new String[]{ADN_PHONE_NUMBER_COLUMN_NAME}, null, null, null); 21391197049c458f07092b31501d2ed512180b13d58Chiao Cheng 21491197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (sPreviousAdnQueryHandler != null) { 21591197049c458f07092b31501d2ed512180b13d58Chiao Cheng // It is harmless to call cancel() even after the handler's gone. 21691197049c458f07092b31501d2ed512180b13d58Chiao Cheng sPreviousAdnQueryHandler.cancel(); 21791197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 21891197049c458f07092b31501d2ed512180b13d58Chiao Cheng sPreviousAdnQueryHandler = handler; 21991197049c458f07092b31501d2ed512180b13d58Chiao Cheng return true; 22091197049c458f07092b31501d2ed512180b13d58Chiao Cheng } catch (NumberFormatException ex) { 22191197049c458f07092b31501d2ed512180b13d58Chiao Cheng // Ignore 22291197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 22391197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 22491197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 22591197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 22691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 22791197049c458f07092b31501d2ed512180b13d58Chiao Cheng static boolean handlePinEntry(Context context, String input) { 22891197049c458f07092b31501d2ed512180b13d58Chiao Cheng if ((input.startsWith("**04") || input.startsWith("**05")) && input.endsWith("#")) { 2299dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunn TelecomManager telecomManager = 2309dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunn (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); 2319dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunn return telecomManager.handleMmi(input); 23291197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 23391197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 23491197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 23591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 23691197049c458f07092b31501d2ed512180b13d58Chiao Cheng static boolean handleIMEIDisplay(Context context, String input, boolean useSystemWindow) { 23791197049c458f07092b31501d2ed512180b13d58Chiao Cheng TelephonyManager telephonyManager = 23891197049c458f07092b31501d2ed512180b13d58Chiao Cheng (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 23991197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (telephonyManager != null && input.equals(MMI_IMEI_DISPLAY)) { 24062280c72fd651b00dd5499f4c3b32f30be57ce0dYorke Lee int phoneType = telephonyManager.getPhoneType(); 24191197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (phoneType == TelephonyManager.PHONE_TYPE_GSM) { 24291197049c458f07092b31501d2ed512180b13d58Chiao Cheng showIMEIPanel(context, useSystemWindow, telephonyManager); 24391197049c458f07092b31501d2ed512180b13d58Chiao Cheng return true; 24491197049c458f07092b31501d2ed512180b13d58Chiao Cheng } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) { 24591197049c458f07092b31501d2ed512180b13d58Chiao Cheng showMEIDPanel(context, useSystemWindow, telephonyManager); 24691197049c458f07092b31501d2ed512180b13d58Chiao Cheng return true; 24791197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 24891197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 24991197049c458f07092b31501d2ed512180b13d58Chiao Cheng 25091197049c458f07092b31501d2ed512180b13d58Chiao Cheng return false; 25191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 25291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 2531d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby private static boolean handleRegulatoryInfoDisplay(Context context, String input) { 2541d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby if (input.equals(MMI_REGULATORY_INFO_DISPLAY)) { 2551d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby Log.d(TAG, "handleRegulatoryInfoDisplay() sending intent to settings app"); 256f4f47665942b34a1bab272b84f223bb06825a57fJeff Sharkey Intent showRegInfoIntent = new Intent(Settings.ACTION_SHOW_REGULATORY_INFO); 2571d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby try { 2581d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby context.startActivity(showRegInfoIntent); 2591d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby } catch (ActivityNotFoundException e) { 2601d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby Log.e(TAG, "startActivity() failed: " + e); 2611d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby } 2621d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby return true; 2631d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby } 2641d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby return false; 2651d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby } 2661d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby 26791197049c458f07092b31501d2ed512180b13d58Chiao Cheng // TODO: Combine showIMEIPanel() and showMEIDPanel() into a single 26891197049c458f07092b31501d2ed512180b13d58Chiao Cheng // generic "showDeviceIdPanel()" method, like in the apps/Phone 26991197049c458f07092b31501d2ed512180b13d58Chiao Cheng // version of SpecialCharSequenceMgr.java. (This will require moving 27091197049c458f07092b31501d2ed512180b13d58Chiao Cheng // the phone app's TelephonyCapabilities.getDeviceIdLabel() method 27191197049c458f07092b31501d2ed512180b13d58Chiao Cheng // into the telephony framework, though.) 27291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 27391197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static void showIMEIPanel(Context context, boolean useSystemWindow, 27491197049c458f07092b31501d2ed512180b13d58Chiao Cheng TelephonyManager telephonyManager) { 27591197049c458f07092b31501d2ed512180b13d58Chiao Cheng String imeiStr = telephonyManager.getDeviceId(); 27691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 27791197049c458f07092b31501d2ed512180b13d58Chiao Cheng AlertDialog alert = new AlertDialog.Builder(context) 27891197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setTitle(R.string.imei) 27991197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setMessage(imeiStr) 28091197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setPositiveButton(android.R.string.ok, null) 28191197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setCancelable(false) 28291197049c458f07092b31501d2ed512180b13d58Chiao Cheng .show(); 28391197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 28491197049c458f07092b31501d2ed512180b13d58Chiao Cheng 28591197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static void showMEIDPanel(Context context, boolean useSystemWindow, 28691197049c458f07092b31501d2ed512180b13d58Chiao Cheng TelephonyManager telephonyManager) { 28791197049c458f07092b31501d2ed512180b13d58Chiao Cheng String meidStr = telephonyManager.getDeviceId(); 28891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 28991197049c458f07092b31501d2ed512180b13d58Chiao Cheng AlertDialog alert = new AlertDialog.Builder(context) 29091197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setTitle(R.string.meid) 29191197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setMessage(meidStr) 29291197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setPositiveButton(android.R.string.ok, null) 29391197049c458f07092b31501d2ed512180b13d58Chiao Cheng .setCancelable(false) 29491197049c458f07092b31501d2ed512180b13d58Chiao Cheng .show(); 29591197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 29691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 29791197049c458f07092b31501d2ed512180b13d58Chiao Cheng /******* 29891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * This code is used to handle SIM Contact queries 29991197049c458f07092b31501d2ed512180b13d58Chiao Cheng *******/ 30091197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static final String ADN_PHONE_NUMBER_COLUMN_NAME = "number"; 30191197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static final String ADN_NAME_COLUMN_NAME = "name"; 30291197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static final int ADN_QUERY_TOKEN = -1; 30391197049c458f07092b31501d2ed512180b13d58Chiao Cheng 30491197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 30591197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Cookie object that contains everything we need to communicate to the 30691197049c458f07092b31501d2ed512180b13d58Chiao Cheng * handler's onQuery Complete, as well as what we need in order to cancel 30791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * the query (if requested). 30891197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 30991197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Note, access to the textField field is going to be synchronized, because 31091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * the user can request a cancel at any time through the UI. 31191197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 31291197049c458f07092b31501d2ed512180b13d58Chiao Cheng private static class SimContactQueryCookie implements DialogInterface.OnCancelListener{ 31391197049c458f07092b31501d2ed512180b13d58Chiao Cheng public ProgressDialog progressDialog; 31491197049c458f07092b31501d2ed512180b13d58Chiao Cheng public int contactNum; 31591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 31691197049c458f07092b31501d2ed512180b13d58Chiao Cheng // Used to identify the query request. 31791197049c458f07092b31501d2ed512180b13d58Chiao Cheng private int mToken; 31891197049c458f07092b31501d2ed512180b13d58Chiao Cheng private QueryHandler mHandler; 31991197049c458f07092b31501d2ed512180b13d58Chiao Cheng 32091197049c458f07092b31501d2ed512180b13d58Chiao Cheng // The text field we're going to update 32191197049c458f07092b31501d2ed512180b13d58Chiao Cheng private EditText textField; 32291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 32391197049c458f07092b31501d2ed512180b13d58Chiao Cheng public SimContactQueryCookie(int number, QueryHandler handler, int token) { 32491197049c458f07092b31501d2ed512180b13d58Chiao Cheng contactNum = number; 32591197049c458f07092b31501d2ed512180b13d58Chiao Cheng mHandler = handler; 32691197049c458f07092b31501d2ed512180b13d58Chiao Cheng mToken = token; 32791197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 32891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 32991197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 33091197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Synchronized getter for the EditText. 33191197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 33291197049c458f07092b31501d2ed512180b13d58Chiao Cheng public synchronized EditText getTextField() { 33391197049c458f07092b31501d2ed512180b13d58Chiao Cheng return textField; 33491197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 33591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 33691197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 33791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Synchronized setter for the EditText. 33891197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 33991197049c458f07092b31501d2ed512180b13d58Chiao Cheng public synchronized void setTextField(EditText text) { 34091197049c458f07092b31501d2ed512180b13d58Chiao Cheng textField = text; 34191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 34291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 34391197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 34491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Cancel the ADN query by stopping the operation and signaling 34591197049c458f07092b31501d2ed512180b13d58Chiao Cheng * the cookie that a cancel request is made. 34691197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 34791197049c458f07092b31501d2ed512180b13d58Chiao Cheng public synchronized void onCancel(DialogInterface dialog) { 34891197049c458f07092b31501d2ed512180b13d58Chiao Cheng // close the progress dialog 34991197049c458f07092b31501d2ed512180b13d58Chiao Cheng if (progressDialog != null) { 35091197049c458f07092b31501d2ed512180b13d58Chiao Cheng progressDialog.dismiss(); 35191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 35291197049c458f07092b31501d2ed512180b13d58Chiao Cheng 35391197049c458f07092b31501d2ed512180b13d58Chiao Cheng // setting the textfield to null ensures that the UI does NOT get 35491197049c458f07092b31501d2ed512180b13d58Chiao Cheng // updated. 35591197049c458f07092b31501d2ed512180b13d58Chiao Cheng textField = null; 35691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 35791197049c458f07092b31501d2ed512180b13d58Chiao Cheng // Cancel the operation if possible. 35891197049c458f07092b31501d2ed512180b13d58Chiao Cheng mHandler.cancelOperation(mToken); 35991197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 36091197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 36191197049c458f07092b31501d2ed512180b13d58Chiao Cheng 36291197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 36391197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Asynchronous query handler that services requests to look up ADNs 36491197049c458f07092b31501d2ed512180b13d58Chiao Cheng * 3651d6fb57f3a53db34bfcb3dacdf11bcb6fb091b06Jake Hamby * Queries originate from {@link #handleAdnEntry}. 36691197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 36707af764827a7d6d426f6097d3e769084968f84fdChiao Cheng private static class QueryHandler extends NoNullCursorAsyncQueryHandler { 36891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 36991197049c458f07092b31501d2ed512180b13d58Chiao Cheng private boolean mCanceled; 37091197049c458f07092b31501d2ed512180b13d58Chiao Cheng 37191197049c458f07092b31501d2ed512180b13d58Chiao Cheng public QueryHandler(ContentResolver cr) { 37291197049c458f07092b31501d2ed512180b13d58Chiao Cheng super(cr); 37391197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 37491197049c458f07092b31501d2ed512180b13d58Chiao Cheng 37591197049c458f07092b31501d2ed512180b13d58Chiao Cheng /** 37691197049c458f07092b31501d2ed512180b13d58Chiao Cheng * Override basic onQueryComplete to fill in the textfield when 37791197049c458f07092b31501d2ed512180b13d58Chiao Cheng * we're handed the ADN cursor. 37891197049c458f07092b31501d2ed512180b13d58Chiao Cheng */ 37991197049c458f07092b31501d2ed512180b13d58Chiao Cheng @Override 38007af764827a7d6d426f6097d3e769084968f84fdChiao Cheng protected void onNotNullableQueryComplete(int token, Object cookie, Cursor c) { 381ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner try { 382ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner sPreviousAdnQueryHandler = null; 383ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner if (mCanceled) { 384ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner return; 385ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner } 38691197049c458f07092b31501d2ed512180b13d58Chiao Cheng 387ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner SimContactQueryCookie sc = (SimContactQueryCookie) cookie; 38891197049c458f07092b31501d2ed512180b13d58Chiao Cheng 389ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // close the progress dialog. 390ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner sc.progressDialog.dismiss(); 39191197049c458f07092b31501d2ed512180b13d58Chiao Cheng 392ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // get the EditText to update or see if the request was cancelled. 393ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner EditText text = sc.getTextField(); 39491197049c458f07092b31501d2ed512180b13d58Chiao Cheng 395ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // if the textview is valid, and the cursor is valid and postionable 396ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // on the Nth number, then we update the text field and display a 397ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // toast indicating the caller name. 398ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner if ((c != null) && (text != null) && (c.moveToPosition(sc.contactNum))) { 399ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner String name = c.getString(c.getColumnIndexOrThrow(ADN_NAME_COLUMN_NAME)); 400ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner String number = c.getString(c.getColumnIndexOrThrow(ADN_PHONE_NUMBER_COLUMN_NAME)); 40191197049c458f07092b31501d2ed512180b13d58Chiao Cheng 402ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // fill the text in. 403ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner text.getText().replace(0, 0, number); 40491197049c458f07092b31501d2ed512180b13d58Chiao Cheng 405ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner // display the name as a toast 406ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner Context context = sc.progressDialog.getContext(); 407ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner name = context.getString(R.string.menu_callNumber, name); 408ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner Toast.makeText(context, name, Toast.LENGTH_SHORT) 409ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner .show(); 410ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner } 411ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner } finally { 412ede67ec7813fb2c6fcda485adf82f11b55e3562cJay Shrauner MoreCloseables.closeQuietly(c); 41391197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 41491197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 41591197049c458f07092b31501d2ed512180b13d58Chiao Cheng 41691197049c458f07092b31501d2ed512180b13d58Chiao Cheng public void cancel() { 41791197049c458f07092b31501d2ed512180b13d58Chiao Cheng mCanceled = true; 41891197049c458f07092b31501d2ed512180b13d58Chiao Cheng // Ask AsyncQueryHandler to cancel the whole request. This will fails when the 41991197049c458f07092b31501d2ed512180b13d58Chiao Cheng // query already started. 42091197049c458f07092b31501d2ed512180b13d58Chiao Cheng cancelOperation(ADN_QUERY_TOKEN); 42191197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 42291197049c458f07092b31501d2ed512180b13d58Chiao Cheng } 42391197049c458f07092b31501d2ed512180b13d58Chiao Cheng} 424