• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.phone;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.net.Uri;
24 import android.provider.Telephony.Intents;
25 import com.android.internal.telephony.PhoneFactory;
26 import com.android.internal.telephony.Phone;
27 import android.telephony.PhoneNumberUtils;
28 import android.util.Log;
29 import android.view.WindowManager;
30 
31 /**
32  * Helper class to listen for some magic character sequences
33  * that are handled specially by the Phone app.
34  */
35 public class SpecialCharSequenceMgr {
36     private static final String TAG = PhoneApp.LOG_TAG;
37     private static final boolean DBG = false;
38 
39     private static final String MMI_IMEI_DISPLAY = "*#06#";
40 
41     /** This class is never instantiated. */
SpecialCharSequenceMgr()42     private SpecialCharSequenceMgr() {
43     }
44 
handleChars(Context context, String input)45     static boolean handleChars(Context context, String input) {
46         return handleChars(context, input, false, null);
47     }
48 
49     /**
50      * Generally used for the PUK unlocking case, where we
51      * want to be able to maintain a handle to the calling
52      * activity so that we can close it or otherwise display
53      * indication if the PUK code is recognized.
54      *
55      * NOTE: The counterpart to this file in Contacts does
56      * NOT contain the special PUK handling code, since it
57      * does NOT need it.  When the device gets into PUK-
58      * locked state, the keyguard comes up and the only way
59      * to unlock the device is through the Emergency dialer,
60      * which is still in the Phone App.
61      */
handleChars(Context context, String input, Activity pukInputActivity)62     static boolean handleChars(Context context, String input, Activity pukInputActivity) {
63         return handleChars(context, input, false, pukInputActivity);
64     }
65 
handleChars(Context context, String input, boolean useSystemWindow)66     static boolean handleChars(Context context, String input, boolean useSystemWindow) {
67         return handleChars(context, input, useSystemWindow, null);
68     }
69 
70     /**
71      * Check for special strings of digits from an input
72      * string.
73      *
74      * @param context input Context for the events we handle
75      * @param input the dial string to be examined
76      * @param useSystemWindow used for the IMEI event to
77      * determine display behaviour.
78      * @param pukInputActivity activity that originated this
79      * PUK call, tracked so that we can close it or otherwise
80      * indicate that special character sequence is
81      * successfully processed.
82      */
handleChars(Context context, String input, boolean useSystemWindow, Activity pukInputActivity)83     static boolean handleChars(Context context,
84                                String input,
85                                boolean useSystemWindow,
86                                Activity pukInputActivity) {
87 
88         //get rid of the separators so that the string gets parsed correctly
89         String dialString = PhoneNumberUtils.stripSeparators(input);
90 
91         if (handleIMEIDisplay(context, dialString, useSystemWindow)
92             || handlePinEntry(context, dialString, pukInputActivity)
93             || handleAdnEntry(context, dialString)
94             || handleSecretCode(context, dialString)) {
95             return true;
96         }
97 
98         return false;
99     }
100 
101     /**
102      * Handles secret codes to launch arbitrary activities in the form of *#*#<code>#*#*.
103      * If a secret code is encountered an Intent is started with the android_secret_code://<code>
104      * URI.
105      *
106      * @param context the context to use
107      * @param input the text to check for a secret code in
108      * @return true if a secret code was encountered
109      */
handleSecretCode(Context context, String input)110     static boolean handleSecretCode(Context context, String input) {
111         // Secret codes are in the form *#*#<code>#*#*
112         int len = input.length();
113         if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
114             Intent intent = new Intent(Intents.SECRET_CODE_ACTION,
115                     Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
116             context.sendBroadcast(intent);
117             return true;
118         }
119 
120         return false;
121     }
122 
handleAdnEntry(Context context, String input)123     static boolean handleAdnEntry(Context context, String input) {
124         /* ADN entries are of the form "N(N)(N)#" */
125 
126         // if the phone is keyguard-restricted, then just ignore this
127         // input.  We want to make sure that sim card contacts are NOT
128         // exposed unless the phone is unlocked, and this code can be
129         // accessed from the emergency dialer.
130         if (PhoneApp.getInstance().getKeyguardManager().inKeyguardRestrictedInputMode()) {
131             return false;
132         }
133 
134         int len = input.length();
135         if ((len > 1) && (len < 5) && (input.endsWith("#"))) {
136             try {
137                 int index = Integer.parseInt(input.substring(0, len-1));
138                 Intent intent = new Intent(Intent.ACTION_PICK);
139 
140                 intent.setClassName("com.android.phone",
141                                     "com.android.phone.SimContacts");
142                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
143                 intent.putExtra("index", index);
144                 PhoneApp.getInstance().startActivity(intent);
145 
146                 return true;
147             } catch (NumberFormatException ex) {}
148         }
149         return false;
150     }
151 
handlePinEntry(Context context, String input, Activity pukInputActivity)152     static boolean handlePinEntry(Context context, String input, Activity pukInputActivity) {
153         // TODO: The string constants here should be removed in favor of some call to a
154         // static the MmiCode class that determines if a dialstring is an MMI code.
155         if ((input.startsWith("**04") || input.startsWith("**05"))
156                 && input.endsWith("#")) {
157             PhoneApp app = PhoneApp.getInstance();
158             boolean isMMIHandled = app.phone.handlePinMmi(input);
159 
160             // if the PUK code is recognized then indicate to the
161             // phone app that an attempt to unPUK the device was
162             // made with this activity.  The PUK code may still
163             // fail though, but we won't know until the MMI code
164             // returns a result.
165             if (isMMIHandled && input.startsWith("**05")) {
166                 app.setPukEntryActivity(pukInputActivity);
167             }
168             return isMMIHandled;
169         }
170         return false;
171     }
172 
handleIMEIDisplay(Context context, String input, boolean useSystemWindow)173     static boolean handleIMEIDisplay(Context context,
174                                      String input, boolean useSystemWindow) {
175         if (input.equals(MMI_IMEI_DISPLAY)) {
176             int phoneType = PhoneApp.getInstance().phone.getPhoneType();
177             if (phoneType == Phone.PHONE_TYPE_CDMA) {
178                 showMEIDPanel(context, useSystemWindow);
179                 return true;
180             } else if (phoneType == Phone.PHONE_TYPE_GSM) {
181                 showIMEIPanel(context, useSystemWindow);
182                 return true;
183             }
184         }
185 
186         return false;
187     }
188 
showIMEIPanel(Context context, boolean useSystemWindow)189     static void showIMEIPanel(Context context, boolean useSystemWindow) {
190         if (DBG) log("showIMEIPanel");
191 
192         String imeiStr = PhoneFactory.getDefaultPhone().getDeviceId();
193 
194         AlertDialog alert = new AlertDialog.Builder(context)
195                 .setTitle(R.string.imei)
196                 .setMessage(imeiStr)
197                 .setPositiveButton(R.string.ok, null)
198                 .setCancelable(false)
199                 .show();
200         alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PRIORITY_PHONE);
201     }
202 
showMEIDPanel(Context context, boolean useSystemWindow)203     static void showMEIDPanel(Context context, boolean useSystemWindow) {
204         if (DBG) log("showMEIDPanel");
205 
206         String meidStr = PhoneFactory.getDefaultPhone().getDeviceId();
207 
208         AlertDialog alert = new AlertDialog.Builder(context)
209                 .setTitle(R.string.meid)
210                 .setMessage(meidStr)
211                 .setPositiveButton(R.string.ok, null)
212                 .setCancelable(false)
213                 .show();
214         alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PRIORITY_PHONE);
215     }
216 
log(String msg)217     private static void log(String msg) {
218         Log.d(TAG, "[SpecialCharSequenceMgr] " + msg);
219     }
220 }
221