1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.voicemail.impl;
18 
19 import android.content.Context;
20 import android.os.Bundle;
21 import android.support.annotation.VisibleForTesting;
22 import android.support.annotation.WorkerThread;
23 import android.telecom.PhoneAccountHandle;
24 import android.telephony.TelephonyManager;
25 import android.text.TextUtils;
26 import com.android.voicemail.VoicemailComponent;
27 import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil;
28 import java.lang.reflect.Method;
29 
30 /** Handles migration of data from the visual voicemail client in telephony before O. */
31 public final class PreOMigrationHandler {
32 
33   // Hidden system APIs to access pre O VVM data
34   // Bundle getVisualVoicemailSettings()
35   private static final String METHOD_GET_VISUAL_VOICEMAIL_SETTINGS = "getVisualVoicemailSettings";
36 
37   /**
38    * Key in bundle returned by {@link #METHOD_GET_VISUAL_VOICEMAIL_SETTINGS}, indicating whether
39    * visual voicemail was enabled or disabled by the user. If the user never explicitly changed this
40    * setting, this key will not exist.
41    */
42   private static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL =
43       "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
44 
45   /**
46    * Key in bundle returned by {@link #METHOD_GET_VISUAL_VOICEMAIL_SETTINGS}, indicating the
47    * voicemail access PIN scrambled during the auto provisioning process. The user is expected to
48    * reset their PIN if this value is not {@code null}.
49    */
50   private static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING =
51       "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
52 
53   @VisibleForTesting static final String PRE_O_MIGRATION_FINISHED = "pre_o_migration_finished";
54 
55   @WorkerThread
migrate(Context context, PhoneAccountHandle phoneAccountHandle)56   public static void migrate(Context context, PhoneAccountHandle phoneAccountHandle) {
57     Assert.isNotMainThread();
58     VisualVoicemailPreferences preferences =
59         new VisualVoicemailPreferences(context, phoneAccountHandle);
60     if (preferences.getBoolean(PRE_O_MIGRATION_FINISHED, false)) {
61       VvmLog.i("PreOMigrationHandler", phoneAccountHandle + " already migrated");
62       return;
63     }
64     VvmLog.i("PreOMigrationHandler", "migrating " + phoneAccountHandle);
65     migrateSettings(context, phoneAccountHandle);
66 
67     preferences.edit().putBoolean(PRE_O_MIGRATION_FINISHED, true).apply();
68   }
69 
migrateSettings(Context context, PhoneAccountHandle phoneAccountHandle)70   private static void migrateSettings(Context context, PhoneAccountHandle phoneAccountHandle) {
71     VvmLog.i("PreOMigrationHandler.migrateSettings", "migrating settings");
72     TelephonyManager telephonyManager =
73         context
74             .getSystemService(TelephonyManager.class)
75             .createForPhoneAccountHandle(phoneAccountHandle);
76     if (telephonyManager == null) {
77       VvmLog.e("PreOMigrationHandler.migrateSettings", "invalid PhoneAccountHandle");
78       return;
79     }
80     Bundle legacySettings;
81     try {
82       Method method = TelephonyManager.class.getMethod(METHOD_GET_VISUAL_VOICEMAIL_SETTINGS);
83       legacySettings = (Bundle) method.invoke(telephonyManager);
84     } catch (ReflectiveOperationException | ClassCastException e) {
85       VvmLog.i("PreOMigrationHandler.migrateSettings", "unable to retrieve settings from system");
86       return;
87     }
88 
89     if (legacySettings.containsKey(EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL)) {
90       boolean enabled = legacySettings.getBoolean(EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL);
91       VvmLog.i("PreOMigrationHandler.migrateSettings", "setting VVM enabled to " + enabled);
92       VisualVoicemailSettingsUtil.setEnabled(context, phoneAccountHandle, enabled);
93     }
94 
95     if (legacySettings.containsKey(EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING)) {
96       String scrambledPin = legacySettings.getString(EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING);
97       if (!TextUtils.isEmpty(scrambledPin)) {
98         VvmLog.i("PreOMigrationHandler.migrateSettings", "migrating scrambled PIN");
99         VoicemailComponent.get(context)
100             .getVoicemailClient()
101             .createPinChanger(context, phoneAccountHandle)
102             .setScrambledPin(scrambledPin);
103       }
104     }
105   }
106 }
107