• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  * <p>http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * <p>Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11  * express or implied. See the License for the specific language governing permissions and
12  * limitations under the License
13  */
14 package com.android.voicemail.impl;
15 
16 import android.annotation.TargetApi;
17 import android.content.Context;
18 import android.content.Intent;
19 import android.content.SharedPreferences;
20 import android.os.Build.VERSION_CODES;
21 import android.os.PersistableBundle;
22 import android.preference.PreferenceManager;
23 import android.provider.VoicemailContract.Status;
24 import android.provider.VoicemailContract.Voicemails;
25 import android.support.annotation.MainThread;
26 import android.support.annotation.NonNull;
27 import android.support.annotation.Nullable;
28 import android.support.v4.os.BuildCompat;
29 import android.telecom.PhoneAccountHandle;
30 import android.telephony.TelephonyManager;
31 import com.android.dialer.common.Assert;
32 import com.android.dialer.common.LogUtil;
33 import com.android.dialer.configprovider.ConfigProviderBindings;
34 import com.android.voicemail.PinChanger;
35 import com.android.voicemail.VisualVoicemailTypeExtensions;
36 import com.android.voicemail.VoicemailClient;
37 import com.android.voicemail.VoicemailVersionConstants;
38 import com.android.voicemail.impl.configui.VoicemailSecretCodeActivity;
39 import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil;
40 import com.android.voicemail.impl.sync.VvmAccountManager;
41 import com.android.voicemail.impl.transcribe.TranscriptionBackfillService;
42 import com.android.voicemail.impl.transcribe.TranscriptionConfigProvider;
43 import java.util.List;
44 import javax.inject.Inject;
45 
46 /**
47  * {@link VoicemailClient} to be used when the voicemail module is activated. May only be used above
48  * O.
49  */
50 public class VoicemailClientImpl implements VoicemailClient {
51 
52   /**
53    * List of legacy OMTP voicemail packages that should be ignored. It could never be the active VVM
54    * package anymore. For example, voicemails in OC will no longer be handled by telephony, but
55    * legacy voicemails might still exist in the database due to upgrading from NYC. Dialer will
56    * fetch these voicemails again so it should be ignored.
57    */
58   private static final String[] OMTP_VOICEMAIL_BLACKLIST = {"com.android.phone"};
59 
60   // Flag name used for configuration
61   private static final String ALLOW_VOICEMAIL_ARCHIVE = "allow_voicemail_archive";
62 
63   private static final String[] OMTP_VOICEMAIL_TYPE = {
64     TelephonyManager.VVM_TYPE_OMTP,
65     TelephonyManager.VVM_TYPE_CVVM,
66     VisualVoicemailTypeExtensions.VVM_TYPE_VVM3
67   };
68 
69   @Inject
VoicemailClientImpl()70   public VoicemailClientImpl() {
71     Assert.checkArgument(BuildCompat.isAtLeastO());
72   }
73 
74   @Override
isVoicemailModuleEnabled()75   public boolean isVoicemailModuleEnabled() {
76     return true;
77   }
78 
79   @Override
hasCarrierSupport(Context context, PhoneAccountHandle phoneAccountHandle)80   public boolean hasCarrierSupport(Context context, PhoneAccountHandle phoneAccountHandle) {
81     OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle);
82     return config.isValid() && !config.isCarrierAppInstalled();
83   }
84 
85   @Override
isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle)86   public boolean isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
87     return VisualVoicemailSettingsUtil.isEnabled(context, phoneAccountHandle);
88   }
89 
90   @Override
setVoicemailEnabled( Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled)91   public void setVoicemailEnabled(
92       Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {
93     VisualVoicemailSettingsUtil.setEnabled(context, phoneAccountHandle, enabled);
94   }
95 
96   @Override
isVoicemailArchiveEnabled(Context context, PhoneAccountHandle phoneAccountHandle)97   public boolean isVoicemailArchiveEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
98     return VisualVoicemailSettingsUtil.isArchiveEnabled(context, phoneAccountHandle);
99   }
100 
101   @Override
isVoicemailArchiveAvailable(Context context)102   public boolean isVoicemailArchiveAvailable(Context context) {
103     if (!BuildCompat.isAtLeastO()) {
104       LogUtil.i("VoicemailClientImpl.isVoicemailArchiveAllowed", "not running on O or later");
105       return false;
106     }
107 
108     if (!ConfigProviderBindings.get(context).getBoolean(ALLOW_VOICEMAIL_ARCHIVE, false)) {
109       LogUtil.i(
110           "VoicemailClientImpl.isVoicemailArchiveAllowed",
111           "feature disabled by config: %s",
112           ALLOW_VOICEMAIL_ARCHIVE);
113       return false;
114     }
115 
116     return true;
117   }
118 
119   @Override
setVoicemailArchiveEnabled( Context context, PhoneAccountHandle phoneAccountHandle, boolean value)120   public void setVoicemailArchiveEnabled(
121       Context context, PhoneAccountHandle phoneAccountHandle, boolean value) {
122     VisualVoicemailSettingsUtil.setArchiveEnabled(context, phoneAccountHandle, value);
123   }
124 
125   @Override
isVoicemailTranscriptionAvailable(Context context)126   public boolean isVoicemailTranscriptionAvailable(Context context) {
127     if (!BuildCompat.isAtLeastO()) {
128       LogUtil.i(
129           "VoicemailClientImpl.isVoicemailTranscriptionAvailable", "not running on O or later");
130       return false;
131     }
132 
133     TranscriptionConfigProvider provider = new TranscriptionConfigProvider(context);
134     if (!provider.isVoicemailTranscriptionAvailable()) {
135       LogUtil.i(
136           "VoicemailClientImpl.isVoicemailTranscriptionAvailable", "feature disabled by config");
137       return false;
138     }
139 
140     return true;
141   }
142 
143   @Override
isVoicemailDonationAvailable(Context context)144   public boolean isVoicemailDonationAvailable(Context context) {
145     if (!isVoicemailTranscriptionAvailable(context)) {
146       LogUtil.i("VoicemailClientImpl.isVoicemailDonationAvailable", "transcription not available");
147       return false;
148     }
149 
150     TranscriptionConfigProvider provider = new TranscriptionConfigProvider(context);
151     if (!provider.isVoicemailDonationAvailable()) {
152       LogUtil.i("VoicemailClientImpl.isVoicemailDonationAvailable", "feature disabled by config");
153       return false;
154     }
155 
156     return true;
157   }
158 
159   @Override
isVoicemailDonationEnabled(Context context, PhoneAccountHandle account)160   public boolean isVoicemailDonationEnabled(Context context, PhoneAccountHandle account) {
161     return isVoicemailTranscriptionAvailable(context)
162         && VisualVoicemailSettingsUtil.isVoicemailDonationEnabled(context, account);
163   }
164 
165   @Override
setVoicemailDonationEnabled( Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled)166   public void setVoicemailDonationEnabled(
167       Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {
168     VisualVoicemailSettingsUtil.setVoicemailDonationEnabled(context, phoneAccountHandle, enabled);
169   }
170 
171   @Override
isActivated(Context context, PhoneAccountHandle phoneAccountHandle)172   public boolean isActivated(Context context, PhoneAccountHandle phoneAccountHandle) {
173     return VvmAccountManager.isAccountActivated(context, phoneAccountHandle);
174   }
175 
176   @Override
showConfigUi(@onNull Context context)177   public void showConfigUi(@NonNull Context context) {
178     Intent intent = new Intent(context, VoicemailSecretCodeActivity.class);
179     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
180     context.startActivity(intent);
181   }
182 
183   @Override
getConfig(Context context, PhoneAccountHandle phoneAccountHandle)184   public PersistableBundle getConfig(Context context, PhoneAccountHandle phoneAccountHandle) {
185     return new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle).getConfig();
186   }
187 
188   @Override
189   @MainThread
onBoot(@onNull Context context)190   public void onBoot(@NonNull Context context) {
191     OmtpService.onBoot(context);
192     StatusCheckJobService.schedule(context);
193   }
194 
195   @Override
196   @MainThread
onShutdown(@onNull Context context)197   public void onShutdown(@NonNull Context context) {
198     OmtpService.onShutdown(context);
199   }
200 
201   @Override
addActivationStateListener(ActivationStateListener listener)202   public void addActivationStateListener(ActivationStateListener listener) {
203     VvmAccountManager.addListener(listener);
204   }
205 
206   @Override
removeActivationStateListener(ActivationStateListener listener)207   public void removeActivationStateListener(ActivationStateListener listener) {
208     VvmAccountManager.removeListener(listener);
209   }
210 
211   @Override
createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle)212   public PinChanger createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle) {
213     return new PinChangerImpl(context, phoneAccountHandle);
214   }
215 
216   @TargetApi(VERSION_CODES.O)
217   @Override
appendOmtpVoicemailSelectionClause( Context context, StringBuilder where, List<String> selectionArgs)218   public void appendOmtpVoicemailSelectionClause(
219       Context context, StringBuilder where, List<String> selectionArgs) {
220     String omtpSource =
221         context.getSystemService(TelephonyManager.class).getVisualVoicemailPackageName();
222     if (where.length() != 0) {
223       where.append(" AND ");
224     }
225     where.append("(");
226     {
227       where.append("(");
228       {
229         where.append(Voicemails.IS_OMTP_VOICEMAIL).append(" != 1");
230         where.append(")");
231       }
232       where.append(" OR ");
233       where.append("(");
234       {
235         where.append(Voicemails.SOURCE_PACKAGE).append(" = ?");
236         selectionArgs.add(omtpSource);
237         where.append(")");
238       }
239       where.append(")");
240     }
241 
242     for (String blacklistedPackage : OMTP_VOICEMAIL_BLACKLIST) {
243       where.append("AND (").append(Voicemails.SOURCE_PACKAGE).append("!= ?)");
244       selectionArgs.add(blacklistedPackage);
245     }
246   }
247 
248   @TargetApi(VERSION_CODES.O)
249   @Override
appendOmtpVoicemailStatusSelectionClause( Context context, StringBuilder where, List<String> selectionArgs)250   public void appendOmtpVoicemailStatusSelectionClause(
251       Context context, StringBuilder where, List<String> selectionArgs) {
252     String omtpSource =
253         context.getSystemService(TelephonyManager.class).getVisualVoicemailPackageName();
254     if (where.length() != 0) {
255       where.append(" AND ");
256     }
257     where.append("(");
258     {
259       where.append("(");
260       {
261         where.append(Status.SOURCE_PACKAGE).append(" = ? ");
262         selectionArgs.add(omtpSource);
263         where.append(")");
264       }
265       where.append(" OR NOT (");
266       {
267         for (int i = 0; i < OMTP_VOICEMAIL_TYPE.length; i++) {
268           if (i != 0) {
269             where.append(" OR ");
270           }
271           where.append(" (");
272           {
273             where.append(Status.SOURCE_TYPE).append(" IS ?");
274             selectionArgs.add(OMTP_VOICEMAIL_TYPE[i]);
275             where.append(")");
276           }
277         }
278         where.append(")");
279       }
280       for (String blacklistedPackage : OMTP_VOICEMAIL_BLACKLIST) {
281         where.append("AND (");
282         {
283           where.append(Voicemails.SOURCE_PACKAGE).append("!= ?");
284           selectionArgs.add(blacklistedPackage);
285           where.append(")");
286         }
287       }
288       where.append(")");
289     }
290   }
291 
292   @Override
onTosAccepted(Context context, PhoneAccountHandle account)293   public void onTosAccepted(Context context, PhoneAccountHandle account) {
294     LogUtil.i("VoicemailClientImpl.onTosAccepted", "try backfilling voicemail transcriptions");
295     TranscriptionBackfillService.scheduleTask(context, account);
296   }
297 
298   @Override
hasAcceptedTos(Context context, PhoneAccountHandle phoneAccountHandle)299   public boolean hasAcceptedTos(Context context, PhoneAccountHandle phoneAccountHandle) {
300     SharedPreferences preferences =
301         PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
302     OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle);
303     boolean isVvm3 = VisualVoicemailTypeExtensions.VVM_TYPE_VVM3.equals(helper.getVvmType());
304     if (isVvm3) {
305       return preferences.getInt(VoicemailVersionConstants.PREF_VVM3_TOS_VERSION_ACCEPTED_KEY, 0)
306           >= VoicemailVersionConstants.CURRENT_VVM3_TOS_VERSION;
307     } else {
308       return preferences.getInt(VoicemailVersionConstants.PREF_DIALER_TOS_VERSION_ACCEPTED_KEY, 0)
309           >= VoicemailVersionConstants.CURRENT_DIALER_TOS_VERSION;
310     }
311   }
312 
313   @Override
314   @Nullable
getCarrierConfigString(Context context, PhoneAccountHandle account, String key)315   public String getCarrierConfigString(Context context, PhoneAccountHandle account, String key) {
316     OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, account);
317     return helper.isValid() ? helper.getString(key) : null;
318   }
319 }
320