17d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/*
27d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Copyright (C) 2006 The Android Open Source Project
37d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
47d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
57d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * you may not use this file except in compliance with the License.
67d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * You may obtain a copy of the License at
77d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
87d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
97d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Unless required by applicable law or agreed to in writing, software
117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * See the License for the specific language governing permissions and
147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * limitations under the License.
157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpackage com.android.phone;
187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.Notification;
207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.NotificationManager;
217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.PendingIntent;
227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.StatusBarManager;
237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.ComponentName;
247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Context;
257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Intent;
267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.SharedPreferences;
2799d0ac2c693849e959601a275128a739569d2efbAndrew Leeimport android.content.pm.UserInfo;
28b4a9270ef0cd337732e6e88d9cf4ff5f72fb94d2Nancy Chenimport android.content.res.Resources;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.net.Uri;
30c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseriimport android.os.PersistableBundle;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.SystemProperties;
3299d0ac2c693849e959601a275128a739569d2efbAndrew Leeimport android.os.UserHandle;
3399d0ac2c693849e959601a275128a739569d2efbAndrew Leeimport android.os.UserManager;
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.preference.PreferenceManager;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.provider.ContactsContract.PhoneLookup;
364d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.PhoneAccount;
37d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Leeimport android.telecom.PhoneAccountHandle;
38d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Leeimport android.telecom.TelecomManager;
393649bdb5813200904d4e887306dfebb1a0beffa8Jonathan Basseriimport android.telephony.CarrierConfigManager;
407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.PhoneNumberUtils;
417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.ServiceState;
422fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Leeimport android.telephony.SubscriptionInfo;
43a82b820e69f41585c3a2b76678040b93fdf54886Andrew Leeimport android.telephony.SubscriptionManager;
44fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yenimport android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
45d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Leeimport android.telephony.TelephonyManager;
467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
479c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunnimport android.util.ArrayMap;
487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.widget.Toast;
50b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen
517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.TelephonyCapabilities;
5341fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yenimport com.android.phone.settings.VoicemailNotificationSettingsUtil;
54bf07f76dd57457da159b5d5504e391afbb4a3592Andrew Leeimport com.android.phone.settings.VoicemailSettingsActivity;
552cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chenimport com.android.phone.vvm.omtp.sync.VoicemailStatusQueryHelper;
56b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen
579c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunnimport java.util.Iterator;
5899d0ac2c693849e959601a275128a739569d2efbAndrew Leeimport java.util.List;
599c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunnimport java.util.Set;
6099d0ac2c693849e959601a275128a739569d2efbAndrew Lee
617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * NotificationManager-related utility code for the Phone app.
637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * This is a singleton object which acts as the interface to the
657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * framework's NotificationManager, and is used to display status bar
667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * icons and control other status bar-related behavior.
677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * @see PhoneGlobals.notificationMgr
697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
70312b9c9112948c8ca7f74ea91b5e2585a66482c9Chiao Chengpublic class NotificationMgr {
71a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee    private static final String LOG_TAG = NotificationMgr.class.getSimpleName();
727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG =
737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Do not check in with VDBG = true, since that may write PII to the system log.
757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean VDBG = false;
767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
77b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen    private static final String MWI_SHOULD_CHECK_VVM_CONFIGURATION_KEY_PREFIX =
78b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen            "mwi_should_check_vvm_configuration_state_";
79b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen
807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // notification types
81f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon    static final int MMI_NOTIFICATION = 1;
82f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon    static final int NETWORK_SELECTION_NOTIFICATION = 2;
83f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon    static final int VOICEMAIL_NOTIFICATION = 3;
84f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon    static final int CALL_FORWARD_NOTIFICATION = 4;
85f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon    static final int DATA_DISCONNECTED_ROAMING_NOTIFICATION = 5;
86f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon    static final int SELECTED_OPERATOR_FAIL_NOTIFICATION = 6;
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The singleton NotificationMgr instance. */
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static NotificationMgr sInstance;
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private PhoneGlobals mApp;
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Phone mPhone;
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Context mContext;
957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private NotificationManager mNotificationManager;
965dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee    private final ComponentName mNotificationComponent;
977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private StatusBarManager mStatusBarManager;
9899d0ac2c693849e959601a275128a739569d2efbAndrew Lee    private UserManager mUserManager;
997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Toast mToast;
1002fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee    private SubscriptionManager mSubscriptionManager;
101d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee    private TelecomManager mTelecomManager;
102d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee    private TelephonyManager mTelephonyManager;
1037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // used to track the notification of selected network unavailable
1057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private boolean mSelectedUnavailableNotify = false;
1067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1079c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    // used to track whether the message waiting indicator is visible, per subscription id.
1089c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    private ArrayMap<Integer, Boolean> mMwiVisible = new ArrayMap<Integer, Boolean>();
1099c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn
1107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Private constructor (this is a singleton).
112f68db2ef27f3bdf14f0053c46d73df910bd394f2Santos Cordon     * @see #init(PhoneGlobals)
1137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private NotificationMgr(PhoneGlobals app) {
1157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
1167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mContext = app;
1177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mNotificationManager =
1187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
1197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mStatusBarManager =
1207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                (StatusBarManager) app.getSystemService(Context.STATUS_BAR_SERVICE);
12199d0ac2c693849e959601a275128a739569d2efbAndrew Lee        mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
122dcf40a9cc562d95f826123d8d670262c8d15e7bdStuart Scott        mPhone = app.mCM.getDefaultPhone();
1232fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee        mSubscriptionManager = SubscriptionManager.from(mContext);
124d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee        mTelecomManager = TelecomManager.from(mContext);
125d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee        mTelephonyManager = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE);
1265dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
1275dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee        final String notificationComponent = mContext.getString(
1285dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                R.string.config_customVoicemailComponent);
1295dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
1305dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee        mNotificationComponent = notificationComponent != null
1315dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                ? ComponentName.unflattenFromString(notificationComponent) : null;
132fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen
133fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen        mSubscriptionManager.addOnSubscriptionsChangedListener(
134fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen                new OnSubscriptionsChangedListener() {
135fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen                    @Override
136fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen                    public void onSubscriptionsChanged() {
137fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen                        updateActivePhonesMwi();
138fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen                    }
139fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen                });
140fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen    }
141fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen
142fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen    public void updateActivePhonesMwi() {
143fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen        List<SubscriptionInfo> subInfos = mSubscriptionManager.getActiveSubscriptionInfoList();
144fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen
145fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen        if (subInfos == null) {
146fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen            return;
147fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen        }
148fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen
149fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen        for (int i = 0; i < subInfos.size(); i++) {
150fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen            int subId = subInfos.get(i).getSubscriptionId();
151fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen            refreshMwi(subId);
152fb4f0502ade1f64cd8bdf247281ea11ce83fec85Ta-wei Yen        }
1537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton NotificationMgr instance.
1577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
1587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
1597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * From then on, the NotificationMgr instance is available via the
1607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * PhoneApp's public "notificationMgr" field, which is why there's no
1617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * getInstance() method here.
1627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /* package */ static NotificationMgr init(PhoneGlobals app) {
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (NotificationMgr.class) {
1657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
1667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                sInstance = new NotificationMgr(app);
1677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
1687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
1697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
1707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
1717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The projection to use when querying the phones table */
1757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    static final String[] PHONES_PROJECTION = new String[] {
1767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        PhoneLookup.NUMBER,
1777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        PhoneLookup.DISPLAY_NAME,
1787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        PhoneLookup._ID
1797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    };
1807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1829c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * Re-creates the message waiting indicator (voicemail) notification if it is showing.  Used to
1839c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * refresh the voicemail intent on the indicator when the user changes it via the voicemail
1849c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * settings screen.  The voicemail notification sound is suppressed.
1859c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     *
1869c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * @param subId The subscription Id.
1879c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     */
1889c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    /* package */ void refreshMwi(int subId) {
1899c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        // In a single-sim device, subId can be -1 which means "no sub id".  In this case we will
1909c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        // reference the single subid stored in the mMwiVisible map.
1919c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        if (subId == SubscriptionInfoHelper.NO_SUB_ID) {
1929c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            if (mMwiVisible.keySet().size() == 1) {
1939c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                Set<Integer> keySet = mMwiVisible.keySet();
1949c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                Iterator<Integer> keyIt = keySet.iterator();
1959c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                if (!keyIt.hasNext()) {
1969c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                    return;
1979c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                }
1989c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                subId = keyIt.next();
1999c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            }
2009c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        }
2019c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        if (mMwiVisible.containsKey(subId)) {
2029c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            boolean mwiVisible = mMwiVisible.get(subId);
2039c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            if (mwiVisible) {
2049c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                updateMwi(subId, mwiVisible, false /* enableNotificationSound */);
2059c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            }
2069c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        }
2079c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    }
2089c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn
209b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen    public void setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled) {
210b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
211b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen            Log.e(LOG_TAG, "setShouldCheckVisualVoicemailConfigurationForMwi: invalid subId"
212b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen                    + subId);
213b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen            return;
214b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        }
215b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen
216b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        PreferenceManager.getDefaultSharedPreferences(mContext).edit()
217b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen                .putBoolean(MWI_SHOULD_CHECK_VVM_CONFIGURATION_KEY_PREFIX + subId, enabled)
218b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen                .apply();
219b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen    }
220b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen
221b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen    private boolean shouldCheckVisualVoicemailConfigurationForMwi(int subId) {
222b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
223b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen            Log.e(LOG_TAG, "shouldCheckVisualVoicemailConfigurationForMwi: invalid subId" + subId);
224b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen            return true;
225b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        }
226b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        return PreferenceManager
227b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen                .getDefaultSharedPreferences(mContext)
228b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen                .getBoolean(MWI_SHOULD_CHECK_VVM_CONFIGURATION_KEY_PREFIX + subId, true);
229b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen    }
2309c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    /**
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Updates the message waiting indicator (voicemail) notification.
2327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
2337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @param visible true if there are messages waiting
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
2352fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee    /* package */ void updateMwi(int subId, boolean visible) {
2369c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn        updateMwi(subId, visible, true /* enableNotificationSound */);
2379c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    }
2389c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn
2399c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    /**
2409c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * Updates the message waiting indicator (voicemail) notification.
2419c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     *
2429c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * @param subId the subId to update.
2439c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * @param visible true if there are messages waiting
2449c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     * @param enableNotificationSound {@code true} if the notification sound should be played.
2459c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn     */
2469c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn    void updateMwi(int subId, boolean visible, boolean enableNotificationSound) {
247a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee        if (!PhoneGlobals.sVoiceCapable) {
248a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            // Do not show the message waiting indicator on devices which are not voice capable.
249a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            // These events *should* be blocked at the telephony layer for such devices.
250a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            Log.w(LOG_TAG, "Called updateMwi() on non-voice-capable device! Ignoring...");
251a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            return;
252a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee        }
253a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee
2542cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen        Phone phone = PhoneGlobals.getPhone(subId);
255b29425b49c3ed353a114291712ef4d484ef645c5Ta-wei Yen        if (visible && phone != null && shouldCheckVisualVoicemailConfigurationForMwi(subId)) {
2562cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen            VoicemailStatusQueryHelper queryHelper = new VoicemailStatusQueryHelper(mContext);
2572cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen            PhoneAccountHandle phoneAccount = PhoneUtils.makePstnPhoneAccountHandle(phone);
25841fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen            if (queryHelper.isVoicemailSourceConfigured(phoneAccount)) {
25941fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen                Log.v(LOG_TAG, "Source configured for visual voicemail, hiding mwi.");
26041fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen                // MWI may not be suppressed if the PIN is not set on VVM3 because it is also a
26141fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen                // "Not OK" configuration state. But VVM3 never send a MWI after the service is
26241fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen                // activated so this should be fine.
26341fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen                // TODO(twyen): once unbundled the client should be able to set a flag to suppress
26441fb43ee2ee41c73fab478afb4b270fff9f276c7Ta-wei Yen                // MWI, instead of letting the NotificationMgr try to interpret the states.
2652cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen                visible = false;
2662cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen            }
2672cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen        }
2682cf7f2935c71b0ddbdda86fa6bc18b33db2dbf99Nancy Chen
26967a62a2dd4941b983ed92f53b330a7c902408c5dYorke Lee        Log.i(LOG_TAG, "updateMwi(): subId " + subId + " update to " + visible);
270f8ad78f133fc0841d2cd6947f5be3aa94cf2252eAndrew Lee        mMwiVisible.put(subId, visible);
271f8ad78f133fc0841d2cd6947f5be3aa94cf2252eAndrew Lee
2727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (visible) {
2732fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            if (phone == null) {
274d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                Log.w(LOG_TAG, "Found null phone for: " + subId);
275d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                return;
276d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            }
277d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee
278d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId);
279d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            if (subInfo == null) {
280d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                Log.w(LOG_TAG, "Found null subscription info for: " + subId);
2812fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                return;
2822fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            }
2832fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee
2847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int resId = android.R.drawable.stat_notify_voicemail;
2857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // This Notification can get a lot fancier once we have more
2877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // information about the current voicemail messages.
2887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // (For example, the current voicemail system can't tell
2897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // us the caller-id or timestamp of a message, or tell us the
2907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // message count.)
2917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // But for now, the UI is ultra-simple: if the MWI indication
2937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is supposed to be visible, just show a single generic
2947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // notification.
2957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            String notificationTitle = mContext.getString(R.string.notification_voicemail_title);
2972fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            String vmNumber = phone.getVoiceMailNumber();
2987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG) log("- got vm number: '" + vmNumber + "'");
2997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
300a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            // The voicemail number may be null because:
301a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            //   (1) This phone has no voicemail number.
302a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            //   (2) This phone has a voicemail number, but the SIM isn't ready yet. This may
303a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            //       happen when the device first boots if we get a MWI notification when we
304a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee            //       register on the network before the SIM has loaded. In this case, the
3052fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            //       SubscriptionListener in CallNotifier will update this once the SIM is loaded.
3062fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            if ((vmNumber == null) && !phone.getIccRecordsLoaded()) {
3077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG) log("- Null vm number: SIM records not loaded (yet)...");
308a82b820e69f41585c3a2b76678040b93fdf54886Andrew Lee                return;
3097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
3107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3115dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            Integer vmCount = null;
3125dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
3132fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            if (TelephonyCapabilities.supportsVoiceMessageCount(phone)) {
3145dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                vmCount = phone.getVoiceMessageCount();
3157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                String titleFormat = mContext.getString(R.string.notification_voicemail_title_count);
3167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                notificationTitle = String.format(titleFormat, vmCount);
3177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
3187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3199c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            // This pathway only applies to PSTN accounts; only SIMS have subscription ids.
3209c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            PhoneAccountHandle phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(phone);
3219c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn
3229c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            Intent intent;
3237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            String notificationText;
3245dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            boolean isSettingsIntent = TextUtils.isEmpty(vmNumber);
3255dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
3265dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            if (isSettingsIntent) {
3279c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                notificationText = mContext.getString(
3289c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                        R.string.notification_voicemail_no_vm_number);
3299c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn
3309c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                // If the voicemail number if unknown, instead of calling voicemail, take the user
3319c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                // to the voicemail settings.
3329c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                notificationText = mContext.getString(
3339c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                        R.string.notification_voicemail_no_vm_number);
334bf07f76dd57457da159b5d5504e391afbb4a3592Andrew Lee                intent = new Intent(VoicemailSettingsActivity.ACTION_ADD_VOICEMAIL);
3359c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                intent.putExtra(SubscriptionInfoHelper.SUB_ID_EXTRA, subId);
336bf07f76dd57457da159b5d5504e391afbb4a3592Andrew Lee                intent.setClass(mContext, VoicemailSettingsActivity.class);
3377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
3389c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                if (mTelephonyManager.getPhoneCount() > 1) {
3399c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                    notificationText = subInfo.getDisplayName().toString();
340d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                } else {
341d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                    notificationText = String.format(
342d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                            mContext.getString(R.string.notification_voicemail_text_format),
343d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                            PhoneNumberUtils.formatNumber(vmNumber));
344d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                }
3459c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                intent = new Intent(
3469c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                        Intent.ACTION_CALL, Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "",
3473649bdb5813200904d4e887306dfebb1a0beffa8Jonathan Basseri                                null));
3489c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn                intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
3497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
3507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3512fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            PendingIntent pendingIntent =
3522fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                    PendingIntent.getActivity(mContext, subId /* requestCode */, intent, 0);
3539c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            Uri ringtoneUri = null;
3549c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn
3559c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            if (enableNotificationSound) {
3569b37a873360aedd575d7ed189939fb0ad9f9251cTa-wei Yen                ringtoneUri = VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
3579c1071fdb42947afd215b0f4f3e81f871b1ff581Tyler Gunn            }
3587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
359b4a9270ef0cd337732e6e88d9cf4ff5f72fb94d2Nancy Chen            Resources res = mContext.getResources();
360c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri            PersistableBundle carrierConfig = PhoneGlobals.getInstance().getCarrierConfigForSubId(
3619b37a873360aedd575d7ed189939fb0ad9f9251cTa-wei Yen                    subId);
3627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Notification.Builder builder = new Notification.Builder(mContext);
3637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            builder.setSmallIcon(resId)
3647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    .setWhen(System.currentTimeMillis())
365d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                    .setColor(subInfo.getIconTint())
3667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    .setContentTitle(notificationTitle)
3677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    .setContentText(notificationText)
3687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    .setContentIntent(pendingIntent)
369acb5f74aff9bd9e15ec21f421e79bc555faaff20Yorke Lee                    .setSound(ringtoneUri)
370b4a9270ef0cd337732e6e88d9cf4ff5f72fb94d2Nancy Chen                    .setColor(res.getColor(R.color.dialer_theme_color))
3713649bdb5813200904d4e887306dfebb1a0beffa8Jonathan Basseri                    .setOngoing(carrierConfig.getBoolean(
3729504c6b5c5c7072f72d8a9e6df59dbda8a6ccbe4Jonathan Basseri                            CarrierConfigManager.KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL));
3737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3742fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            if (VoicemailNotificationSettingsUtil.isVibrationEnabled(phone)) {
37599d0ac2c693849e959601a275128a739569d2efbAndrew Lee                builder.setDefaults(Notification.DEFAULT_VIBRATE);
37699d0ac2c693849e959601a275128a739569d2efbAndrew Lee            }
37799d0ac2c693849e959601a275128a739569d2efbAndrew Lee
37899d0ac2c693849e959601a275128a739569d2efbAndrew Lee            final Notification notification = builder.build();
37999d0ac2c693849e959601a275128a739569d2efbAndrew Lee            List<UserInfo> users = mUserManager.getUsers(true);
38099d0ac2c693849e959601a275128a739569d2efbAndrew Lee            for (int i = 0; i < users.size(); i++) {
381047b1f9f0af3c9a0a285eb944b409a785040707cYorke Lee                final UserInfo user = users.get(i);
382047b1f9f0af3c9a0a285eb944b409a785040707cYorke Lee                final UserHandle userHandle = user.getUserHandle();
38399d0ac2c693849e959601a275128a739569d2efbAndrew Lee                if (!mUserManager.hasUserRestriction(
384047b1f9f0af3c9a0a285eb944b409a785040707cYorke Lee                        UserManager.DISALLOW_OUTGOING_CALLS, userHandle)
3853649bdb5813200904d4e887306dfebb1a0beffa8Jonathan Basseri                        && !user.isManagedProfile()) {
3865dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                    if (!sendNotificationCustomComponent(vmCount, vmNumber, pendingIntent,
3875dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                            isSettingsIntent)) {
3885dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                        mNotificationManager.notifyAsUser(
3895dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                                Integer.toString(subId) /* tag */,
3905dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                                VOICEMAIL_NOTIFICATION,
3915dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                                notification,
3925dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                                userHandle);
3935dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                    }
39499d0ac2c693849e959601a275128a739569d2efbAndrew Lee                }
3957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
3967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
3975dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            if (!sendNotificationCustomComponent(0, null, null, false)) {
3985dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                mNotificationManager.cancelAsUser(
3995dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                        Integer.toString(subId) /* tag */,
4005dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                        VOICEMAIL_NOTIFICATION,
4015dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                        UserHandle.ALL);
4025dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            }
4035dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee        }
4045dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee    }
4055dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
4065dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee    /**
4075dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * Sends a broadcast with the voicemail notification information to a custom component to
4085dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * handle. This method is also used to indicate to the custom component when to clear the
4095dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * notification. A pending intent can be passed to the custom component to indicate an action to
4105dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * be taken as it would by a notification produced in this class.
4115dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * @param count The number of pending voicemail messages to indicate on the notification. A
4125dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     *              Value of 0 is passed here to indicate that the notification should be cleared.
4135dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * @param number The voicemail phone number if specified.
4145dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * @param pendingIntent The intent that should be passed as the action to be taken.
4155dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * @param isSettingsIntent {@code true} to indicate the pending intent is to launch settings.
4165dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     *                         otherwise, {@code false} to indicate the intent launches voicemail.
4175dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     * @return {@code true} if a custom component was notified of the notification.
4185dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee     */
4195dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee    private boolean sendNotificationCustomComponent(Integer count, String number,
4205dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            PendingIntent pendingIntent, boolean isSettingsIntent) {
4215dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee        if (mNotificationComponent != null) {
4225dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            Intent intent = new Intent();
4235dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
4245dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            intent.setComponent(mNotificationComponent);
4255dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            intent.setAction(TelephonyManager.ACTION_SHOW_VOICEMAIL_NOTIFICATION);
4265dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
4275dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            if (count != null) {
4285dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                intent.putExtra(TelephonyManager.EXTRA_NOTIFICATION_COUNT, count);
4295dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            }
4305dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
4315dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            // Additional information about the voicemail notification beyond the count is only
4325dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            // present when the count not specified or greater than 0. The value of 0 represents
4335dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            // clearing the notification, which does not require additional information.
4345dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            if (count == null || count > 0) {
4355dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                if (!TextUtils.isEmpty(number)) {
4365dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                    intent.putExtra(TelephonyManager.EXTRA_VOICEMAIL_NUMBER, number);
4375dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                }
4385dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
4395dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                if (pendingIntent != null) {
4405dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                    intent.putExtra(isSettingsIntent
4415dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                            ? TelephonyManager.EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT
4425dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                            : TelephonyManager.EXTRA_CALL_VOICEMAIL_INTENT,
4435dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                            pendingIntent);
4445dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee                }
4455dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            }
4465dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
4475dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            mContext.sendBroadcast(intent);
4485dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee            return true;
4497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
4505dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee
4515dc90848c184a5fd35ad5b7c0e9aa1d50911934bBryce Lee        return false;
4527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
4537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
4557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Updates the message call forwarding indicator notification.
4567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
4577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @param visible true if there are messages waiting
4587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
4592fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee    /* package */ void updateCfi(int subId, boolean visible) {
4607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("updateCfi(): " + visible);
4617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (visible) {
4627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If Unconditional Call Forwarding (forward all calls) for VOICE
4637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is enabled, just show a notification.  We'll default to expanded
4647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // view for now, so the there is less confusion about the icon.  If
4657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // it is deemed too weird to have CF indications as expanded views,
4667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // then we'll flip the flag back.
4677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // TODO: We may want to take a look to see if the notification can
4697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // display the target to forward calls to.  This will require some
4707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // effort though, since there are multiple layers of messages that
4717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // will need to propagate that information.
4727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
473d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId);
474d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            if (subInfo == null) {
475d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                Log.w(LOG_TAG, "Found null subscription info for: " + subId);
476d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                return;
477d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            }
478d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee
479d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            String notificationTitle;
480d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            if (mTelephonyManager.getPhoneCount() > 1) {
481d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                notificationTitle = subInfo.getDisplayName().toString();
482d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            } else {
483d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                notificationTitle = mContext.getString(R.string.labelCF);
484d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee            }
485d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee
48699d0ac2c693849e959601a275128a739569d2efbAndrew Lee            Notification.Builder builder = new Notification.Builder(mContext)
48799d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    .setSmallIcon(R.drawable.stat_sys_phone_call_forward)
488d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                    .setColor(subInfo.getIconTint())
489d5165b05c851ecd47d330b600ed2768e0db8b9d1Andrew Lee                    .setContentTitle(notificationTitle)
49099d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    .setContentText(mContext.getString(R.string.sum_cfu_enabled_indicator))
49199d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    .setShowWhen(false)
49299d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    .setOngoing(true);
49399d0ac2c693849e959601a275128a739569d2efbAndrew Lee
49499d0ac2c693849e959601a275128a739569d2efbAndrew Lee            Intent intent = new Intent(Intent.ACTION_MAIN);
4952fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
49699d0ac2c693849e959601a275128a739569d2efbAndrew Lee            intent.setClassName("com.android.phone", "com.android.phone.CallFeaturesSetting");
4972fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            SubscriptionInfoHelper.addExtrasToIntent(
4982fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                    intent, mSubscriptionManager.getActiveSubscriptionInfo(subId));
4992fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee            PendingIntent contentIntent =
5002fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                    PendingIntent.getActivity(mContext, subId /* requestCode */, intent, 0);
50199d0ac2c693849e959601a275128a739569d2efbAndrew Lee
50299d0ac2c693849e959601a275128a739569d2efbAndrew Lee            List<UserInfo> users = mUserManager.getUsers(true);
50399d0ac2c693849e959601a275128a739569d2efbAndrew Lee            for (int i = 0; i < users.size(); i++) {
5043faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                final UserInfo user = users.get(i);
5053faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                if (user.isManagedProfile()) {
5063faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                    continue;
5073faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                }
5083faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                UserHandle userHandle = user.getUserHandle();
5093105e9a01b1cf782e11fd1a6cb3bcefc5633ef67Xiaohui Chen                builder.setContentIntent(user.isAdmin() ? contentIntent : null);
5102fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                mNotificationManager.notifyAsUser(
5112fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                        Integer.toString(subId) /* tag */,
5122fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                        CALL_FORWARD_NOTIFICATION,
5132fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                        builder.build(),
5142fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                        userHandle);
5157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
5167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
51799d0ac2c693849e959601a275128a739569d2efbAndrew Lee            mNotificationManager.cancelAsUser(
5182fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                    Integer.toString(subId) /* tag */,
5192fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                    CALL_FORWARD_NOTIFICATION,
5202fcb6c372c76a48b7af8f9b0dc7fd518698bbf77Andrew Lee                    UserHandle.ALL);
5217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
5257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Shows the "data disconnected due to roaming" notification, which
5267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * appears when you lose data connectivity because you're roaming and
5277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * you have the "data roaming" feature turned off.
5287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
5297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /* package */ void showDataDisconnectedRoaming() {
5307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("showDataDisconnectedRoaming()...");
5317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // "Mobile network settings" screen / dialog
5337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(mContext, com.android.phone.MobileNetworkSettings.class);
53499d0ac2c693849e959601a275128a739569d2efbAndrew Lee        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
5357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final CharSequence contentText = mContext.getText(R.string.roaming_reenable_message);
5377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
53899d0ac2c693849e959601a275128a739569d2efbAndrew Lee        final Notification.Builder builder = new Notification.Builder(mContext)
53999d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setSmallIcon(android.R.drawable.stat_sys_warning)
54099d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setContentTitle(mContext.getText(R.string.roaming))
54199d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
54299d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setContentText(contentText);
54399d0ac2c693849e959601a275128a739569d2efbAndrew Lee
54499d0ac2c693849e959601a275128a739569d2efbAndrew Lee        List<UserInfo> users = mUserManager.getUsers(true);
54599d0ac2c693849e959601a275128a739569d2efbAndrew Lee        for (int i = 0; i < users.size(); i++) {
5463faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            final UserInfo user = users.get(i);
5473faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            if (user.isManagedProfile()) {
5483faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                continue;
5493faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            }
5503faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            UserHandle userHandle = user.getUserHandle();
5513105e9a01b1cf782e11fd1a6cb3bcefc5633ef67Xiaohui Chen            builder.setContentIntent(user.isAdmin() ? contentIntent : null);
55299d0ac2c693849e959601a275128a739569d2efbAndrew Lee            final Notification notif =
55399d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    new Notification.BigTextStyle(builder).bigText(contentText).build();
55499d0ac2c693849e959601a275128a739569d2efbAndrew Lee            mNotificationManager.notifyAsUser(
55599d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    null /* tag */, DATA_DISCONNECTED_ROAMING_NOTIFICATION, notif, userHandle);
55699d0ac2c693849e959601a275128a739569d2efbAndrew Lee        }
5577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
5607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Turns off the "data disconnected due to roaming" notification.
5617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
5627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /* package */ void hideDataDisconnectedRoaming() {
5637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("hideDataDisconnectedRoaming()...");
5647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mNotificationManager.cancel(DATA_DISCONNECTED_ROAMING_NOTIFICATION);
5657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
5687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Display the network selection "no service" notification
5697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @param operator is the numeric operator number
5707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
5717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void showNetworkSelection(String operator) {
5727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("showNetworkSelection(" + operator + ")...");
5737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
57499d0ac2c693849e959601a275128a739569d2efbAndrew Lee        Notification.Builder builder = new Notification.Builder(mContext)
57599d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setSmallIcon(android.R.drawable.stat_sys_warning)
57699d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setContentTitle(mContext.getString(R.string.notification_network_selection_title))
57799d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setContentText(
57899d0ac2c693849e959601a275128a739569d2efbAndrew Lee                        mContext.getString(R.string.notification_network_selection_text, operator))
57999d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setShowWhen(false)
58099d0ac2c693849e959601a275128a739569d2efbAndrew Lee                .setOngoing(true);
5817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // create the target network operators settings intent
5837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_MAIN);
5847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
5857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
5867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Use NetworkSetting to handle the selection intent
587be964583a634a57199417e50b36edb10223f7d3eWei Liu        intent.setComponent(new ComponentName(
588be964583a634a57199417e50b36edb10223f7d3eWei Liu                mContext.getString(R.string.network_operator_settings_package),
589be964583a634a57199417e50b36edb10223f7d3eWei Liu                mContext.getString(R.string.network_operator_settings_class)));
5903e1073d1607d41c87e97cf49ff942afde772725bSanket Padawe        intent.putExtra(GsmUmtsOptions.EXTRA_SUB_ID, mPhone.getSubId());
59199d0ac2c693849e959601a275128a739569d2efbAndrew Lee        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
59299d0ac2c693849e959601a275128a739569d2efbAndrew Lee
59399d0ac2c693849e959601a275128a739569d2efbAndrew Lee        List<UserInfo> users = mUserManager.getUsers(true);
59499d0ac2c693849e959601a275128a739569d2efbAndrew Lee        for (int i = 0; i < users.size(); i++) {
5953faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            final UserInfo user = users.get(i);
5963faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            if (user.isManagedProfile()) {
5973faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee                continue;
5983faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            }
5993faa594099e79c7fa7ac6e4c974e435d2cf4d471Yorke Lee            UserHandle userHandle = user.getUserHandle();
6003105e9a01b1cf782e11fd1a6cb3bcefc5633ef67Xiaohui Chen            builder.setContentIntent(user.isAdmin() ? contentIntent : null);
60199d0ac2c693849e959601a275128a739569d2efbAndrew Lee            mNotificationManager.notifyAsUser(
60299d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    null /* tag */,
60399d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    SELECTED_OPERATOR_FAIL_NOTIFICATION,
60499d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    builder.build(),
60599d0ac2c693849e959601a275128a739569d2efbAndrew Lee                    userHandle);
60699d0ac2c693849e959601a275128a739569d2efbAndrew Lee        }
6077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Turn off the network selection "no service" notification
6117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void cancelNetworkSelection() {
6137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("cancelNetworkSelection()...");
61499d0ac2c693849e959601a275128a739569d2efbAndrew Lee        mNotificationManager.cancelAsUser(
61599d0ac2c693849e959601a275128a739569d2efbAndrew Lee                null /* tag */, SELECTED_OPERATOR_FAIL_NOTIFICATION, UserHandle.ALL);
6167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Update notification about no service of user selected operator
6207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
6217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @param serviceState Phone service state
6227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    void updateNetworkSelection(int serviceState) {
6247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TelephonyCapabilities.supportsNetworkSelection(mPhone)) {
625a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan            int subId = mPhone.getSubId();
626a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan            if (SubscriptionManager.isValidSubscriptionId(subId)) {
627a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                // get the shared preference of network_selection.
628a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                // empty is auto mode, otherwise it is the operator alpha name
629a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                // in case there is no operator name, check the operator numeric
630a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                SharedPreferences sp =
631a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                        PreferenceManager.getDefaultSharedPreferences(mContext);
632a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                String networkSelection =
633c5201f417b58f95c5f1b54de1c101b3a35ad544fAmit Mahajan                        sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
634a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                if (TextUtils.isEmpty(networkSelection)) {
635a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                    networkSelection =
636c5201f417b58f95c5f1b54de1c101b3a35ad544fAmit Mahajan                            sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
637a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                }
6387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
639a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                if (DBG) log("updateNetworkSelection()..." + "state = " +
640a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                        serviceState + " new network " + networkSelection);
6417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
642a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
643a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                        && !TextUtils.isEmpty(networkSelection)) {
6442b846c78ff3b4102e416c81c4a17b976d327ed38Hall Liu                    showNetworkSelection(networkSelection);
6452b846c78ff3b4102e416c81c4a17b976d327ed38Hall Liu                    mSelectedUnavailableNotify = true;
646a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                } else {
647a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                    if (mSelectedUnavailableNotify) {
648a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                        cancelNetworkSelection();
649a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                        mSelectedUnavailableNotify = false;
650a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                    }
6517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
6527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
653a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                if (DBG) log("updateNetworkSelection()..." + "state = " +
654a60be872ccf4fc96584bf99b11129ffa2cbb7c4eAmit Mahajan                        serviceState + " not updating network due to invalid subId " + subId);
6557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /* package */ void postTransientNotification(int notifyId, CharSequence msg) {
6607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mToast != null) {
6617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mToast.cancel();
6627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mToast = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
6657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mToast.show();
6667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void log(String msg) {
6697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, msg);
6707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
672