• 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 android.telephony.PhoneNumberUtils;
27 import android.util.Log;
28 import android.view.WindowManager;
29 
30 /**
31  * Helper class to listen for some magic character sequences
32  * that are handled specially by the Phone app.
33  */
34 public class SpecialCharSequenceMgr {
35     private static final String TAG = PhoneApp.LOG_TAG;
36     private static final boolean DBG = false;
37 
38     private static final String MMI_IMEI_DISPLAY = "*#06#";
39 
40     /** This class is never instantiated. */
SpecialCharSequenceMgr()41     private SpecialCharSequenceMgr() {
42     }
43 
handleChars(Context context, String input)44     static boolean handleChars(Context context, String input) {
45         return handleChars(context, input, false, null);
46     }
47 
48     /**
49      * Generally used for the PUK unlocking case, where we
50      * want to be able to maintain a handle to the calling
51      * activity so that we can close it or otherwise display
52      * indication if the PUK code is recognized.
53      *
54      * NOTE: The counterpart to this file in Contacts does
55      * NOT contain the special PUK handling code, since it
56      * does NOT need it.  When the device gets into PUK-
57      * locked state, the keyguard comes up and the only way
58      * to unlock the device is through the Emergency dialer,
59      * which is still in the Phone App.
60      */
handleChars(Context context, String input, Activity pukInputActivity)61     static boolean handleChars(Context context, String input, Activity pukInputActivity) {
62         return handleChars(context, input, false, pukInputActivity);
63     }
64 
handleChars(Context context, String input, boolean useSystemWindow)65     static boolean handleChars(Context context, String input, boolean useSystemWindow) {
66         return handleChars(context, input, useSystemWindow, null);
67     }
68 
69     /**
70      * Check for special strings of digits from an input
71      * string.
72      *
73      * @param context input Context for the events we handle
74      * @param input the dial string to be examined
75      * @param useSystemWindow used for the IMEI event to
76      * determine display behaviour.
77      * @param pukInputActivity activity that originated this
78      * PUK call, tracked so that we can close it or otherwise
79      * indicate that special character sequence is
80      * successfully processed.
81      */
handleChars(Context context, String input, boolean useSystemWindow, Activity pukInputActivity)82     static boolean handleChars(Context context,
83                                String input,
84                                boolean useSystemWindow,
85                                Activity pukInputActivity) {
86 
87         //get rid of the separators so that the string gets parsed correctly
88         String dialString = PhoneNumberUtils.stripSeparators(input);
89 
90         if (handleIMEIDisplay(context, dialString, useSystemWindow)
91             || handlePinEntry(context, dialString, pukInputActivity)
92             || handleAdnEntry(context, dialString)
93             || handleSecretCode(context, dialString)) {
94             return true;
95         }
96 
97         return false;
98     }
99 
100     /**
101      * Handles secret codes to launch arbitrary activities in the form of *#*#<code>#*#*.
102      * If a secret code is encountered an Intent is started with the android_secret_code://<code>
103      * URI.
104      *
105      * @param context the context to use
106      * @param input the text to check for a secret code in
107      * @return true if a secret code was encountered
108      */
handleSecretCode(Context context, String input)109     static boolean handleSecretCode(Context context, String input) {
110         // Secret codes are in the form *#*#<code>#*#*
111         int len = input.length();
112         if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
113             Intent intent = new Intent(Intents.SECRET_CODE_ACTION,
114                     Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
115             context.sendBroadcast(intent);
116             return true;
117         }
118 
119         return false;
120     }
121 
handleAdnEntry(Context context, String input)122     static boolean handleAdnEntry(Context context, String input) {
123         /* ADN entries are of the form "N(N)(N)#" */
124 
125         // if the phone is keyguard-restricted, then just ignore this
126         // input.  We want to make sure that sim card contacts are NOT
127         // exposed unless the phone is unlocked, and this code can be
128         // accessed from the emergency dialer.
129         if (PhoneApp.getInstance().getKeyguardManager().inKeyguardRestrictedInputMode()) {
130             return false;
131         }
132 
133         int len = input.length();
134         if ((len > 1) && (len < 5) && (input.endsWith("#"))) {
135             try {
136                 int index = Integer.parseInt(input.substring(0, len-1));
137                 Intent intent = new Intent(Intent.ACTION_PICK);
138 
139                 intent.setClassName("com.android.phone",
140                                     "com.android.phone.SimContacts");
141                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
142                 intent.putExtra("index", index);
143                 PhoneApp.getInstance().startActivity(intent);
144 
145                 return true;
146             } catch (NumberFormatException ex) {}
147         }
148         return false;
149     }
150 
handlePinEntry(Context context, String input, Activity pukInputActivity)151     static boolean handlePinEntry(Context context, String input, Activity pukInputActivity) {
152         // TODO: The string constants here should be removed in favor of some call to a
153         // static the MmiCode class that determines if a dialstring is an MMI code.
154         if ((input.startsWith("**04") || input.startsWith("**05"))
155                 && input.endsWith("#")) {
156             PhoneApp app = PhoneApp.getInstance();
157             boolean isMMIHandled = app.phone.handlePinMmi(input);
158 
159             // if the PUK code is recognized then indicate to the
160             // phone app that an attempt to unPUK the device was
161             // made with this activity.  The PUK code may still
162             // fail though, but we won't know until the MMI code
163             // returns a result.
164             if (isMMIHandled && input.startsWith("**05")) {
165                 app.setPukEntryActivity(pukInputActivity);
166             }
167             return isMMIHandled;
168         }
169         return false;
170     }
171 
handleIMEIDisplay(Context context, String input, boolean useSystemWindow)172     static boolean handleIMEIDisplay(Context context,
173                                      String input, boolean useSystemWindow) {
174         if (input.equals(MMI_IMEI_DISPLAY)) {
175             showIMEIPanel(context, useSystemWindow);
176             return true;
177         }
178 
179         return false;
180     }
181 
showIMEIPanel(Context context, boolean useSystemWindow)182     static void showIMEIPanel(Context context, boolean useSystemWindow) {
183         if (DBG) log("showIMEIPanel");
184 
185         String imeiStr = PhoneFactory.getDefaultPhone().getDeviceId();
186 
187         AlertDialog alert = new AlertDialog.Builder(context)
188                 .setTitle(R.string.imei)
189                 .setMessage(imeiStr)
190                 .setPositiveButton(R.string.ok, null)
191                 .setCancelable(false)
192                 .show();
193         alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PRIORITY_PHONE);
194     }
195 
log(String msg)196     private static void log(String msg) {
197         Log.d(TAG, "[SpecialCharSequenceMgr] " + msg);
198     }
199 }
200