Set up activate and deactivate on SIM state change.

Register for sim state changes so that a voicemail source can be added
and removed as appropriate:
- When a sim is added, send an activate sms. (the received status sms is
  processed in OmtpMessageReceiver)
- When a sim is removed, remove the corresponding sync account and
  change the status in the voicemail status table to not configured.

Bug: 19236241
Change-Id: Ida82af1aee9e9a5e7649fcb2fc7dabd436816ef8
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index f7c5939..bd911ac 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -36,6 +36,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.VideoProfile;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -2449,6 +2450,10 @@
                 == Configuration.ORIENTATION_LANDSCAPE;
     }
 
+    public static PhoneAccountHandle makePstnPhoneAccountHandle(String id) {
+        return makePstnPhoneAccountHandleWithPrefix(id, "", false);
+    }
+
     public static PhoneAccountHandle makePstnPhoneAccountHandle(int phoneId) {
         return makePstnPhoneAccountHandle(PhoneFactory.getPhone(phoneId));
     }
@@ -2459,10 +2464,15 @@
 
     public static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
             Phone phone, String prefix, boolean isEmergency) {
-        ComponentName pstnConnectionServiceName = getPstnConnectionServiceName();
         // TODO: Should use some sort of special hidden flag to decorate this account as
         // an emergency-only account
         String id = isEmergency ? "E" : prefix + String.valueOf(phone.getIccSerialNumber());
+        return makePstnPhoneAccountHandleWithPrefix(id, prefix, isEmergency);
+    }
+
+    public static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
+            String id, String prefix, boolean isEmergency) {
+        ComponentName pstnConnectionServiceName = getPstnConnectionServiceName();
         return new PhoneAccountHandle(pstnConnectionServiceName, id);
     }
 
@@ -2484,6 +2494,19 @@
         return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
+    /**
+     * Determine if a given phone account corresponds to an active SIM
+     *
+     * @param sm An instance of the subscription manager so it is not recreated for each calling of
+     * this method.
+     * @param handle The handle for the phone account to check
+     * @return {@code true} If there is an active SIM for this phone account,
+     * {@code false} otherwise.
+     */
+    public static boolean isPhoneAccountActive(SubscriptionManager sm, PhoneAccountHandle handle) {
+        return sm.getActiveSubscriptionInfoForIccIndex(handle.getId()) != null;
+    }
+
     private static ComponentName getPstnConnectionServiceName() {
         return new ComponentName(PhoneGlobals.getInstance(), TelephonyConnectionService.class);
     }
@@ -2497,7 +2520,6 @@
                 }
             }
         }
-
         return null;
     }
 
diff --git a/src/com/android/phone/vvm/omtp/OmtpVvmSyncAccountManager.java b/src/com/android/phone/vvm/omtp/OmtpVvmSyncAccountManager.java
index de39745..a4cf4e8 100644
--- a/src/com/android/phone/vvm/omtp/OmtpVvmSyncAccountManager.java
+++ b/src/com/android/phone/vvm/omtp/OmtpVvmSyncAccountManager.java
@@ -19,8 +19,13 @@
 import android.accounts.AccountManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.provider.VoicemailContract;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.SubscriptionManager;
 import android.util.Log;
 
+import com.android.phone.PhoneUtils;
+
 /**
  * A singleton class designed to assist in OMTP visual voicemail sync behavior.
  */
@@ -34,6 +39,8 @@
 
     private static OmtpVvmSyncAccountManager sInstance = new OmtpVvmSyncAccountManager();
 
+    private Context mContext;
+    private SubscriptionManager mSubscriptionManager;
     private AccountManager mAccountManager;
 
     /**
@@ -42,16 +49,18 @@
     private OmtpVvmSyncAccountManager() {}
 
     public static OmtpVvmSyncAccountManager getInstance(Context context) {
-        sInstance.setAccountManager(context);
+        sInstance.setup(context);
         return sInstance;
     }
 
     /**
-     * Set the account manager so it does not need to be retrieved every time.
-     * @param context The context to get the account manager for.
+     * Set the context and system services so they do not need to be retrieved every time.
+     * @param context The context to get the account manager and subscription manager for.
      */
-    private void setAccountManager(Context context) {
-        if (mAccountManager == null) {
+    private void setup(Context context) {
+        if (mContext == null) {
+            mContext = context;
+            mSubscriptionManager = SubscriptionManager.from(context);
             mAccountManager = AccountManager.get(context);
         }
     }
@@ -74,6 +83,26 @@
     }
 
     /**
+     * When a voicemail source is removed, we don't always know which one was removed. Check the
+     * list of registered sync accounts against the active subscriptions list and remove the
+     * inactive accounts.
+     */
+    public void removeInactiveAccounts() {
+        Account[] registeredAccounts = mAccountManager.getAccountsByType(ACCOUNT_TYPE);
+        for (int i = 0; i < registeredAccounts.length; i++) {
+            PhoneAccountHandle handle = PhoneUtils.makePstnPhoneAccountHandle(
+                    registeredAccounts[i].name);
+            if (!PhoneUtils.isPhoneAccountActive(mSubscriptionManager, handle)) {
+                mAccountManager.removeAccount(registeredAccounts[i], null, null, null);
+                VoicemailContract.Status.setStatus(mContext, handle,
+                        VoicemailContract.Status.CONFIGURATION_STATE_NOT_CONFIGURED,
+                        VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION,
+                        VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
+            }
+        }
+    }
+
+    /**
      * Check if a certain account is registered.
      *
      * @param account The account to look for.
diff --git a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
new file mode 100644
index 0000000..b16b9c2
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.phone.vvm.omtp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.internal.telephony.IccCardConstants;
+
+/**
+ * In order to determine when a SIM is added or removed, this class listens for changes to the
+ * SIM state. On SIM state "absent", this means a SIM was removed. On SIM state "loaded", this means
+ * a SIM is ready.
+ *
+ * When a SIM is added, send an activate SMS. When a SIM is removed, remove the sync accounts and
+ * change the status in the voicemail_status table.
+ */
+public class SimChangeReceiver extends BroadcastReceiver {
+    private final String TAG = "SimChangeReceiver";
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+        Log.i(TAG, state);
+        switch (state) {
+            case IccCardConstants.INTENT_VALUE_ICC_ABSENT:
+                OmtpVvmSyncAccountManager.getInstance(context).removeInactiveAccounts();
+                break;
+            case IccCardConstants.INTENT_VALUE_ICC_LOADED:
+                //TODO: get carrier configuration values and send activation SMS
+                break;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 932fb1a..c00441a 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -97,9 +97,6 @@
                     VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
                     VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
         }
-
-        //TODO: figure out how to pass IMAP credentials to sync adapter
-
         ContentResolver.requestSync(account, VoicemailContract.AUTHORITY, new Bundle());
     }
 }