blob: 77daabb51e173387f76de0af011dcd08518dd1f4 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
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
17package com.android.phone;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.app.StatusBarManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070023import android.content.ComponentName;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070024import android.content.Context;
25import android.content.Intent;
26import android.content.SharedPreferences;
Andrew Lee99d0ac22014-10-10 13:18:04 -070027import android.content.pm.UserInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070028import android.net.Uri;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070029import android.os.SystemProperties;
Andrew Lee99d0ac22014-10-10 13:18:04 -070030import android.os.UserHandle;
31import android.os.UserManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070032import android.preference.PreferenceManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070033import android.provider.ContactsContract.PhoneLookup;
34import android.provider.Settings;
Tyler Gunn4d45d1c2014-09-12 22:17:53 -070035import android.telecom.PhoneAccount;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070036import android.telephony.PhoneNumberUtils;
37import android.telephony.ServiceState;
38import android.text.TextUtils;
39import android.util.Log;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070040import android.widget.Toast;
41
Santos Cordon7d4ddf62013-07-10 11:58:08 -070042import com.android.internal.telephony.Phone;
43import com.android.internal.telephony.PhoneBase;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070044import com.android.internal.telephony.TelephonyCapabilities;
Andrew Lee8d66d812014-11-24 14:54:02 -080045import com.android.phone.settings.VoicemailNotificationSettingsUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070046
Andrew Lee99d0ac22014-10-10 13:18:04 -070047import java.util.List;
48
Santos Cordon7d4ddf62013-07-10 11:58:08 -070049/**
50 * NotificationManager-related utility code for the Phone app.
51 *
52 * This is a singleton object which acts as the interface to the
53 * framework's NotificationManager, and is used to display status bar
54 * icons and control other status bar-related behavior.
55 *
56 * @see PhoneGlobals.notificationMgr
57 */
Chiao Cheng312b9c92013-09-16 15:40:53 -070058public class NotificationMgr {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070059 private static final String LOG_TAG = "NotificationMgr";
60 private static final boolean DBG =
61 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
62 // Do not check in with VDBG = true, since that may write PII to the system log.
63 private static final boolean VDBG = false;
64
Santos Cordon7d4ddf62013-07-10 11:58:08 -070065 // notification types
Santos Cordonf68db2e2014-07-02 14:40:44 -070066 static final int MMI_NOTIFICATION = 1;
67 static final int NETWORK_SELECTION_NOTIFICATION = 2;
68 static final int VOICEMAIL_NOTIFICATION = 3;
69 static final int CALL_FORWARD_NOTIFICATION = 4;
70 static final int DATA_DISCONNECTED_ROAMING_NOTIFICATION = 5;
71 static final int SELECTED_OPERATOR_FAIL_NOTIFICATION = 6;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070072
73 /** The singleton NotificationMgr instance. */
74 private static NotificationMgr sInstance;
75
76 private PhoneGlobals mApp;
77 private Phone mPhone;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070078
79 private Context mContext;
80 private NotificationManager mNotificationManager;
81 private StatusBarManager mStatusBarManager;
Andrew Lee99d0ac22014-10-10 13:18:04 -070082 private UserManager mUserManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070083 private Toast mToast;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070084
85 public StatusBarHelper statusBarHelper;
86
Santos Cordon7d4ddf62013-07-10 11:58:08 -070087 // used to track the notification of selected network unavailable
88 private boolean mSelectedUnavailableNotify = false;
89
90 // Retry params for the getVoiceMailNumber() call; see updateMwi().
91 private static final int MAX_VM_NUMBER_RETRIES = 5;
92 private static final int VM_NUMBER_RETRY_DELAY_MILLIS = 10000;
93 private int mVmNumberRetriesRemaining = MAX_VM_NUMBER_RETRIES;
94
Santos Cordon7d4ddf62013-07-10 11:58:08 -070095 /**
96 * Private constructor (this is a singleton).
Santos Cordonf68db2e2014-07-02 14:40:44 -070097 * @see #init(PhoneGlobals)
Santos Cordon7d4ddf62013-07-10 11:58:08 -070098 */
99 private NotificationMgr(PhoneGlobals app) {
100 mApp = app;
101 mContext = app;
102 mNotificationManager =
103 (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
104 mStatusBarManager =
105 (StatusBarManager) app.getSystemService(Context.STATUS_BAR_SERVICE);
Andrew Lee99d0ac22014-10-10 13:18:04 -0700106 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700107 mPhone = app.phone; // TODO: better style to use mCM.getDefaultPhone() everywhere instead
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700108 statusBarHelper = new StatusBarHelper();
109 }
110
111 /**
112 * Initialize the singleton NotificationMgr instance.
113 *
114 * This is only done once, at startup, from PhoneApp.onCreate().
115 * From then on, the NotificationMgr instance is available via the
116 * PhoneApp's public "notificationMgr" field, which is why there's no
117 * getInstance() method here.
118 */
119 /* package */ static NotificationMgr init(PhoneGlobals app) {
120 synchronized (NotificationMgr.class) {
121 if (sInstance == null) {
122 sInstance = new NotificationMgr(app);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700123 } else {
124 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
125 }
126 return sInstance;
127 }
128 }
129
130 /**
131 * Helper class that's a wrapper around the framework's
132 * StatusBarManager.disable() API.
133 *
134 * This class is used to control features like:
135 *
136 * - Disabling the status bar "notification windowshade"
137 * while the in-call UI is up
138 *
139 * - Disabling notification alerts (audible or vibrating)
140 * while a phone call is active
141 *
142 * - Disabling navigation via the system bar (the "soft buttons" at
143 * the bottom of the screen on devices with no hard buttons)
144 *
145 * We control these features through a single point of control to make
146 * sure that the various StatusBarManager.disable() calls don't
147 * interfere with each other.
148 */
149 public class StatusBarHelper {
150 // Current desired state of status bar / system bar behavior
151 private boolean mIsNotificationEnabled = true;
152 private boolean mIsExpandedViewEnabled = true;
153 private boolean mIsSystemBarNavigationEnabled = true;
154
155 private StatusBarHelper () {
156 }
157
158 /**
159 * Enables or disables auditory / vibrational alerts.
160 *
161 * (We disable these any time a voice call is active, regardless
162 * of whether or not the in-call UI is visible.)
163 */
164 public void enableNotificationAlerts(boolean enable) {
165 if (mIsNotificationEnabled != enable) {
166 mIsNotificationEnabled = enable;
167 updateStatusBar();
168 }
169 }
170
171 /**
172 * Enables or disables the expanded view of the status bar
173 * (i.e. the ability to pull down the "notification windowshade").
174 *
175 * (This feature is disabled by the InCallScreen while the in-call
176 * UI is active.)
177 */
178 public void enableExpandedView(boolean enable) {
179 if (mIsExpandedViewEnabled != enable) {
180 mIsExpandedViewEnabled = enable;
181 updateStatusBar();
182 }
183 }
184
185 /**
186 * Enables or disables the navigation via the system bar (the
187 * "soft buttons" at the bottom of the screen)
188 *
189 * (This feature is disabled while an incoming call is ringing,
190 * because it's easy to accidentally touch the system bar while
191 * pulling the phone out of your pocket.)
192 */
193 public void enableSystemBarNavigation(boolean enable) {
194 if (mIsSystemBarNavigationEnabled != enable) {
195 mIsSystemBarNavigationEnabled = enable;
196 updateStatusBar();
197 }
198 }
199
200 /**
201 * Updates the status bar to reflect the current desired state.
202 */
203 private void updateStatusBar() {
204 int state = StatusBarManager.DISABLE_NONE;
205
206 if (!mIsExpandedViewEnabled) {
207 state |= StatusBarManager.DISABLE_EXPAND;
208 }
209 if (!mIsNotificationEnabled) {
210 state |= StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
211 }
212 if (!mIsSystemBarNavigationEnabled) {
213 // Disable *all* possible navigation via the system bar.
214 state |= StatusBarManager.DISABLE_HOME;
215 state |= StatusBarManager.DISABLE_RECENT;
216 state |= StatusBarManager.DISABLE_BACK;
Christine Chenb685f172013-09-25 18:32:59 -0700217 state |= StatusBarManager.DISABLE_SEARCH;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700218 }
219
220 if (DBG) log("updateStatusBar: state = 0x" + Integer.toHexString(state));
221 mStatusBarManager.disable(state);
222 }
223 }
224
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700225 /** The projection to use when querying the phones table */
226 static final String[] PHONES_PROJECTION = new String[] {
227 PhoneLookup.NUMBER,
228 PhoneLookup.DISPLAY_NAME,
229 PhoneLookup._ID
230 };
231
232 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700233 * Updates the message waiting indicator (voicemail) notification.
234 *
235 * @param visible true if there are messages waiting
236 */
237 /* package */ void updateMwi(boolean visible) {
238 if (DBG) log("updateMwi(): " + visible);
239
240 if (visible) {
241 int resId = android.R.drawable.stat_notify_voicemail;
242
243 // This Notification can get a lot fancier once we have more
244 // information about the current voicemail messages.
245 // (For example, the current voicemail system can't tell
246 // us the caller-id or timestamp of a message, or tell us the
247 // message count.)
248
249 // But for now, the UI is ultra-simple: if the MWI indication
250 // is supposed to be visible, just show a single generic
251 // notification.
252
253 String notificationTitle = mContext.getString(R.string.notification_voicemail_title);
254 String vmNumber = mPhone.getVoiceMailNumber();
255 if (DBG) log("- got vm number: '" + vmNumber + "'");
256
257 // Watch out: vmNumber may be null, for two possible reasons:
258 //
259 // (1) This phone really has no voicemail number
260 //
261 // (2) This phone *does* have a voicemail number, but
262 // the SIM isn't ready yet.
263 //
264 // Case (2) *does* happen in practice if you have voicemail
265 // messages when the device first boots: we get an MWI
266 // notification as soon as we register on the network, but the
267 // SIM hasn't finished loading yet.
268 //
269 // So handle case (2) by retrying the lookup after a short
270 // delay.
271
272 if ((vmNumber == null) && !mPhone.getIccRecordsLoaded()) {
273 if (DBG) log("- Null vm number: SIM records not loaded (yet)...");
274
275 // TODO: rather than retrying after an arbitrary delay, it
276 // would be cleaner to instead just wait for a
277 // SIM_RECORDS_LOADED notification.
278 // (Unfortunately right now there's no convenient way to
279 // get that notification in phone app code. We'd first
280 // want to add a call like registerForSimRecordsLoaded()
281 // to Phone.java and GSMPhone.java, and *then* we could
282 // listen for that in the CallNotifier class.)
283
284 // Limit the number of retries (in case the SIM is broken
285 // or missing and can *never* load successfully.)
286 if (mVmNumberRetriesRemaining-- > 0) {
287 if (DBG) log(" - Retrying in " + VM_NUMBER_RETRY_DELAY_MILLIS + " msec...");
288 mApp.notifier.sendMwiChangedDelayed(VM_NUMBER_RETRY_DELAY_MILLIS);
289 return;
290 } else {
291 Log.w(LOG_TAG, "NotificationMgr.updateMwi: getVoiceMailNumber() failed after "
292 + MAX_VM_NUMBER_RETRIES + " retries; giving up.");
293 // ...and continue with vmNumber==null, just as if the
294 // phone had no VM number set up in the first place.
295 }
296 }
297
298 if (TelephonyCapabilities.supportsVoiceMessageCount(mPhone)) {
299 int vmCount = mPhone.getVoiceMessageCount();
300 String titleFormat = mContext.getString(R.string.notification_voicemail_title_count);
301 notificationTitle = String.format(titleFormat, vmCount);
302 }
303
304 String notificationText;
305 if (TextUtils.isEmpty(vmNumber)) {
306 notificationText = mContext.getString(
307 R.string.notification_voicemail_no_vm_number);
308 } else {
309 notificationText = String.format(
310 mContext.getString(R.string.notification_voicemail_text_format),
311 PhoneNumberUtils.formatNumber(vmNumber));
312 }
313
314 Intent intent = new Intent(Intent.ACTION_CALL,
Jay Shrauner137458b2014-09-05 14:27:25 -0700315 Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700316 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
Andrew Lee8d66d812014-11-24 14:54:02 -0800317 Uri ringtoneUri = VoicemailNotificationSettingsUtil.getRingtoneUri(mContext);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700318
319 Notification.Builder builder = new Notification.Builder(mContext);
320 builder.setSmallIcon(resId)
321 .setWhen(System.currentTimeMillis())
322 .setContentTitle(notificationTitle)
323 .setContentText(notificationText)
324 .setContentIntent(pendingIntent)
Yorke Leeacb5f742014-08-19 09:08:42 -0700325 .setSound(ringtoneUri)
Andrew Lee99d0ac22014-10-10 13:18:04 -0700326 .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
327 .setOngoing(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700328
Andrew Lee8d66d812014-11-24 14:54:02 -0800329 if (VoicemailNotificationSettingsUtil.isVibrationEnabled(mContext)) {
Andrew Lee99d0ac22014-10-10 13:18:04 -0700330 builder.setDefaults(Notification.DEFAULT_VIBRATE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700331 }
Andrew Lee99d0ac22014-10-10 13:18:04 -0700332
333 final Notification notification = builder.build();
334 List<UserInfo> users = mUserManager.getUsers(true);
335 for (int i = 0; i < users.size(); i++) {
Yorke Lee047b1f92014-10-24 10:22:41 -0700336 final UserInfo user = users.get(i);
337 final UserHandle userHandle = user.getUserHandle();
Andrew Lee99d0ac22014-10-10 13:18:04 -0700338 if (!mUserManager.hasUserRestriction(
Yorke Lee047b1f92014-10-24 10:22:41 -0700339 UserManager.DISALLOW_OUTGOING_CALLS, userHandle)
340 && !user.isManagedProfile()) {
Andrew Lee99d0ac22014-10-10 13:18:04 -0700341 mNotificationManager.notifyAsUser(
342 null /* tag */, VOICEMAIL_NOTIFICATION, notification, userHandle);
343 }
344 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700345 } else {
Andrew Lee99d0ac22014-10-10 13:18:04 -0700346 mNotificationManager.cancelAsUser(
347 null /* tag */, VOICEMAIL_NOTIFICATION, UserHandle.ALL);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700348 }
349 }
350
351 /**
352 * Updates the message call forwarding indicator notification.
353 *
354 * @param visible true if there are messages waiting
355 */
356 /* package */ void updateCfi(boolean visible) {
357 if (DBG) log("updateCfi(): " + visible);
358 if (visible) {
359 // If Unconditional Call Forwarding (forward all calls) for VOICE
360 // is enabled, just show a notification. We'll default to expanded
361 // view for now, so the there is less confusion about the icon. If
362 // it is deemed too weird to have CF indications as expanded views,
363 // then we'll flip the flag back.
364
365 // TODO: We may want to take a look to see if the notification can
366 // display the target to forward calls to. This will require some
367 // effort though, since there are multiple layers of messages that
368 // will need to propagate that information.
369
Andrew Lee99d0ac22014-10-10 13:18:04 -0700370 Notification.Builder builder = new Notification.Builder(mContext)
371 .setSmallIcon(R.drawable.stat_sys_phone_call_forward)
372 .setContentTitle(mContext.getString(R.string.labelCF))
373 .setContentText(mContext.getString(R.string.sum_cfu_enabled_indicator))
374 .setShowWhen(false)
375 .setOngoing(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700376
Andrew Lee99d0ac22014-10-10 13:18:04 -0700377 Intent intent = new Intent(Intent.ACTION_MAIN);
378 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
379 intent.setClassName("com.android.phone", "com.android.phone.CallFeaturesSetting");
380 PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
381
382 List<UserInfo> users = mUserManager.getUsers(true);
383 for (int i = 0; i < users.size(); i++) {
Yorke Lee3faa5942014-11-05 16:50:04 -0800384 final UserInfo user = users.get(i);
385 if (user.isManagedProfile()) {
386 continue;
387 }
388 UserHandle userHandle = user.getUserHandle();
Andrew Lee99d0ac22014-10-10 13:18:04 -0700389 builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
390 mNotificationManager.notifyAsUser(
391 null /* tag */, CALL_FORWARD_NOTIFICATION, builder.build(), userHandle);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700392 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700393 } else {
Andrew Lee99d0ac22014-10-10 13:18:04 -0700394 mNotificationManager.cancelAsUser(
395 null /* tag */, CALL_FORWARD_NOTIFICATION, UserHandle.ALL);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700396 }
397 }
398
399 /**
400 * Shows the "data disconnected due to roaming" notification, which
401 * appears when you lose data connectivity because you're roaming and
402 * you have the "data roaming" feature turned off.
403 */
404 /* package */ void showDataDisconnectedRoaming() {
405 if (DBG) log("showDataDisconnectedRoaming()...");
406
407 // "Mobile network settings" screen / dialog
408 Intent intent = new Intent(mContext, com.android.phone.MobileNetworkSettings.class);
Andrew Lee99d0ac22014-10-10 13:18:04 -0700409 PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700410
411 final CharSequence contentText = mContext.getText(R.string.roaming_reenable_message);
412
Andrew Lee99d0ac22014-10-10 13:18:04 -0700413 final Notification.Builder builder = new Notification.Builder(mContext)
414 .setSmallIcon(android.R.drawable.stat_sys_warning)
415 .setContentTitle(mContext.getText(R.string.roaming))
416 .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
417 .setContentText(contentText);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700418
Andrew Lee99d0ac22014-10-10 13:18:04 -0700419 List<UserInfo> users = mUserManager.getUsers(true);
420 for (int i = 0; i < users.size(); i++) {
Yorke Lee3faa5942014-11-05 16:50:04 -0800421 final UserInfo user = users.get(i);
422 if (user.isManagedProfile()) {
423 continue;
424 }
425 UserHandle userHandle = user.getUserHandle();
Andrew Lee99d0ac22014-10-10 13:18:04 -0700426 builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
427 final Notification notif =
428 new Notification.BigTextStyle(builder).bigText(contentText).build();
429 mNotificationManager.notifyAsUser(
430 null /* tag */, DATA_DISCONNECTED_ROAMING_NOTIFICATION, notif, userHandle);
431 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700432 }
433
434 /**
435 * Turns off the "data disconnected due to roaming" notification.
436 */
437 /* package */ void hideDataDisconnectedRoaming() {
438 if (DBG) log("hideDataDisconnectedRoaming()...");
439 mNotificationManager.cancel(DATA_DISCONNECTED_ROAMING_NOTIFICATION);
440 }
441
442 /**
443 * Display the network selection "no service" notification
444 * @param operator is the numeric operator number
445 */
446 private void showNetworkSelection(String operator) {
447 if (DBG) log("showNetworkSelection(" + operator + ")...");
448
Andrew Lee99d0ac22014-10-10 13:18:04 -0700449 Notification.Builder builder = new Notification.Builder(mContext)
450 .setSmallIcon(android.R.drawable.stat_sys_warning)
451 .setContentTitle(mContext.getString(R.string.notification_network_selection_title))
452 .setContentText(
453 mContext.getString(R.string.notification_network_selection_text, operator))
454 .setShowWhen(false)
455 .setOngoing(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700456
457 // create the target network operators settings intent
458 Intent intent = new Intent(Intent.ACTION_MAIN);
459 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
460 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
461 // Use NetworkSetting to handle the selection intent
462 intent.setComponent(new ComponentName("com.android.phone",
463 "com.android.phone.NetworkSetting"));
Andrew Lee99d0ac22014-10-10 13:18:04 -0700464 PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700465
Andrew Lee99d0ac22014-10-10 13:18:04 -0700466 List<UserInfo> users = mUserManager.getUsers(true);
467 for (int i = 0; i < users.size(); i++) {
Yorke Lee3faa5942014-11-05 16:50:04 -0800468 final UserInfo user = users.get(i);
469 if (user.isManagedProfile()) {
470 continue;
471 }
472 UserHandle userHandle = user.getUserHandle();
Andrew Lee99d0ac22014-10-10 13:18:04 -0700473 builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
474 mNotificationManager.notifyAsUser(
475 null /* tag */,
476 SELECTED_OPERATOR_FAIL_NOTIFICATION,
477 builder.build(),
478 userHandle);
479 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700480 }
481
482 /**
483 * Turn off the network selection "no service" notification
484 */
485 private void cancelNetworkSelection() {
486 if (DBG) log("cancelNetworkSelection()...");
Andrew Lee99d0ac22014-10-10 13:18:04 -0700487 mNotificationManager.cancelAsUser(
488 null /* tag */, SELECTED_OPERATOR_FAIL_NOTIFICATION, UserHandle.ALL);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700489 }
490
491 /**
492 * Update notification about no service of user selected operator
493 *
494 * @param serviceState Phone service state
495 */
496 void updateNetworkSelection(int serviceState) {
497 if (TelephonyCapabilities.supportsNetworkSelection(mPhone)) {
498 // get the shared preference of network_selection.
499 // empty is auto mode, otherwise it is the operator alpha name
500 // in case there is no operator name, check the operator numeric
501 SharedPreferences sp =
502 PreferenceManager.getDefaultSharedPreferences(mContext);
503 String networkSelection =
504 sp.getString(PhoneBase.NETWORK_SELECTION_NAME_KEY, "");
505 if (TextUtils.isEmpty(networkSelection)) {
506 networkSelection =
507 sp.getString(PhoneBase.NETWORK_SELECTION_KEY, "");
508 }
509
510 if (DBG) log("updateNetworkSelection()..." + "state = " +
511 serviceState + " new network " + networkSelection);
512
513 if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
514 && !TextUtils.isEmpty(networkSelection)) {
515 if (!mSelectedUnavailableNotify) {
516 showNetworkSelection(networkSelection);
517 mSelectedUnavailableNotify = true;
518 }
519 } else {
520 if (mSelectedUnavailableNotify) {
521 cancelNetworkSelection();
522 mSelectedUnavailableNotify = false;
523 }
524 }
525 }
526 }
527
528 /* package */ void postTransientNotification(int notifyId, CharSequence msg) {
529 if (mToast != null) {
530 mToast.cancel();
531 }
532
533 mToast = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
534 mToast.show();
535 }
536
537 private void log(String msg) {
538 Log.d(LOG_TAG, msg);
539 }
540}