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.configui;
18 
19 import android.content.Context;
20 import android.content.SharedPreferences;
21 import android.os.Bundle;
22 import android.os.PersistableBundle;
23 import android.preference.EditTextPreference;
24 import android.preference.Preference;
25 import android.preference.Preference.OnPreferenceChangeListener;
26 import android.preference.PreferenceFragment;
27 import android.preference.PreferenceManager;
28 import android.preference.PreferenceScreen;
29 import android.preference.SwitchPreference;
30 import android.support.annotation.Nullable;
31 import android.support.annotation.VisibleForTesting;
32 import android.telecom.PhoneAccount;
33 import android.telecom.PhoneAccountHandle;
34 import android.telecom.TelecomManager;
35 import android.text.TextUtils;
36 import com.android.dialer.common.Assert;
37 import com.android.dialer.common.concurrent.ThreadUtil;
38 import com.android.dialer.strictmode.StrictModeUtils;
39 import com.android.voicemail.VoicemailComponent;
40 
41 /**
42  * Fragment to edit the override values for the {@link import
43  * com.android.voicemail.impl.OmtpVvmCarrierConfigHelper}
44  */
45 public class ConfigOverrideFragment extends PreferenceFragment
46     implements OnPreferenceChangeListener {
47 
48   /**
49    * Any preference with key that starts with this prefix will be written to the dialer carrier
50    * config.
51    */
52   @VisibleForTesting
53   public static final String CONFIG_OVERRIDE_KEY_PREFIX = "vvm_config_override_key_";
54 
55   @Override
onCreate(@ullable Bundle savedInstanceState)56   public void onCreate(@Nullable Bundle savedInstanceState) {
57     super.onCreate(savedInstanceState);
58     PreferenceManager.setDefaultValues(getActivity(), R.xml.vvm_config_override, false);
59     addPreferencesFromResource(R.xml.vvm_config_override);
60 
61     // add listener so the value of a EditTextPreference will be updated to the summary.
62     for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
63       Preference preference = getPreferenceScreen().getPreference(i);
64       preference.setOnPreferenceChangeListener(this);
65       updatePreference(preference);
66     }
67   }
68 
69   @Override
onPreferenceChange(Preference preference, Object newValue)70   public boolean onPreferenceChange(Preference preference, Object newValue) {
71     Assert.isMainThread();
72     ThreadUtil.postOnUiThread(() -> updatePreference(preference));
73     return true;
74   }
75 
updatePreference(Preference preference)76   private void updatePreference(Preference preference) {
77     if (preference instanceof EditTextPreference) {
78       EditTextPreference editTextPreference = (EditTextPreference) preference;
79       editTextPreference.setSummary(editTextPreference.getText());
80     }
81   }
82 
83   @Override
onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)84   public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
85     if (TextUtils.equals(
86         preference.getKey(), getString(R.string.vvm_config_override_load_current_key))) {
87       loadCurrentConfig();
88     }
89     return super.onPreferenceTreeClick(preferenceScreen, preference);
90   }
91 
92   /**
93    * Loads the config for the currently carrier into the override values, from the dialer or the
94    * carrier config app. This is a "reset" button to load the defaults.
95    */
loadCurrentConfig()96   private void loadCurrentConfig() {
97     Context context = getActivity();
98     PhoneAccountHandle phoneAccountHandle =
99         context
100             .getSystemService(TelecomManager.class)
101             .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_VOICEMAIL);
102 
103     PersistableBundle config =
104         VoicemailComponent.get(context).getVoicemailClient().getConfig(context, phoneAccountHandle);
105 
106     for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
107       Preference preference = getPreferenceScreen().getPreference(i);
108       String key = preference.getKey();
109       if (!key.startsWith(CONFIG_OVERRIDE_KEY_PREFIX)) {
110         continue;
111       }
112 
113       String configKey = key.substring(CONFIG_OVERRIDE_KEY_PREFIX.length());
114 
115       if (configKey.endsWith("bool")) {
116         ((SwitchPreference) preference).setChecked(config.getBoolean(configKey));
117       } else if (configKey.endsWith("int")) {
118         ((EditTextPreference) preference).setText(String.valueOf(config.getInt(configKey)));
119       } else if (configKey.endsWith("string")) {
120         ((EditTextPreference) preference).setText(config.getString(configKey));
121       } else if (configKey.endsWith("string_array")) {
122         ((EditTextPreference) preference).setText(toCsv(config.getStringArray(configKey)));
123       } else {
124         throw Assert.createAssertionFailException("unknown type for key " + configKey);
125       }
126       updatePreference(preference);
127     }
128   }
129 
isOverridden(Context context)130   public static boolean isOverridden(Context context) {
131     return StrictModeUtils.bypass(
132         () ->
133             PreferenceManager.getDefaultSharedPreferences(context)
134                 .getBoolean(context.getString(R.string.vvm_config_override_enabled_key), false));
135   }
136 
getConfig(Context context)137   public static PersistableBundle getConfig(Context context) {
138     Assert.checkState(isOverridden(context));
139     PersistableBundle result = new PersistableBundle();
140 
141     SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
142     for (String key : preferences.getAll().keySet()) {
143       if (!key.startsWith(CONFIG_OVERRIDE_KEY_PREFIX)) {
144         continue;
145       }
146       String configKey = key.substring(CONFIG_OVERRIDE_KEY_PREFIX.length());
147       if (configKey.endsWith("bool")) {
148         result.putBoolean(configKey, preferences.getBoolean(key, false));
149       } else if (configKey.endsWith("int")) {
150         result.putInt(configKey, Integer.valueOf(preferences.getString(key, null)));
151       } else if (configKey.endsWith("string")) {
152         result.putString(configKey, preferences.getString(key, null));
153       } else if (configKey.endsWith("string_array")) {
154         result.putStringArray(configKey, fromCsv(preferences.getString(key, null)));
155       } else {
156         throw Assert.createAssertionFailException("unknown type for key " + configKey);
157       }
158     }
159     return result;
160   }
161 
toCsv(String[] array)162   private static String toCsv(String[] array) {
163     if (array == null) {
164       return "";
165     }
166     StringBuilder result = new StringBuilder();
167     for (String element : array) {
168       if (result.length() != 0) {
169         result.append(",");
170       }
171       result.append(element);
172     }
173     return result.toString();
174   };
175 
fromCsv(String csv)176   private static String[] fromCsv(String csv) {
177     return csv.split(",");
178   }
179 }
180