1 /*
2  * Copyright (C) 2015 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 package com.android.voicemail.impl.settings;
17 
18 import android.content.ContentValues;
19 import android.content.Context;
20 import android.provider.CallLog;
21 import android.provider.CallLog.Calls;
22 import android.provider.VoicemailContract.Voicemails;
23 import android.support.annotation.VisibleForTesting;
24 import android.telecom.PhoneAccountHandle;
25 import com.android.dialer.common.Assert;
26 import com.android.dialer.common.LogUtil;
27 import com.android.dialer.common.concurrent.DialerExecutor.Worker;
28 import com.android.dialer.common.concurrent.DialerExecutorComponent;
29 import com.android.dialer.common.database.Selection;
30 import com.android.dialer.compat.android.provider.VoicemailCompat;
31 import com.android.voicemail.VoicemailComponent;
32 import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
33 import com.android.voicemail.impl.VisualVoicemailPreferences;
34 import com.android.voicemail.impl.VvmLog;
35 import com.android.voicemail.impl.sync.VvmAccountManager;
36 
37 /** Save whether or not a particular account is enabled in shared to be retrieved later. */
38 public class VisualVoicemailSettingsUtil {
39 
40   @VisibleForTesting public static final String IS_ENABLED_KEY = "is_enabled";
41   private static final String ARCHIVE_ENABLED_KEY = "archive_is_enabled";
42   private static final String TRANSCRIBE_VOICEMAILS_KEY = "transcribe_voicemails";
43   private static final String DONATE_VOICEMAILS_KEY = "donate_voicemails";
44 
setEnabled( Context context, PhoneAccountHandle phoneAccount, boolean isEnabled)45   public static void setEnabled(
46       Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) {
47     VvmLog.i("VisualVoicemailSettingsUtil.setEnable", phoneAccount + " enabled:" + isEnabled);
48     new VisualVoicemailPreferences(context, phoneAccount)
49         .edit()
50         .putBoolean(IS_ENABLED_KEY, isEnabled)
51         .apply();
52     OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(context, phoneAccount);
53     if (isEnabled) {
54       config.startActivation();
55     } else {
56       VvmAccountManager.removeAccount(context, phoneAccount);
57       config.startDeactivation();
58       // Remove all voicemails from the database
59       DialerExecutorComponent.get(context)
60           .dialerExecutorFactory()
61           .createNonUiTaskBuilder(new VoicemailDeleteWorker(context))
62           .onSuccess(VisualVoicemailSettingsUtil::onSuccess)
63           .onFailure(VisualVoicemailSettingsUtil::onFailure)
64           .build()
65           .executeParallel(null);
66     }
67   }
68 
onSuccess(Void unused)69   private static void onSuccess(Void unused) {
70     VvmLog.i("VisualVoicemailSettingsUtil.onSuccess", "delete voicemails");
71   }
72 
onFailure(Throwable t)73   private static void onFailure(Throwable t) {
74     VvmLog.e("VisualVoicemailSettingsUtil.onFailure", "delete voicemails", t);
75   }
76 
setArchiveEnabled( Context context, PhoneAccountHandle phoneAccount, boolean isEnabled)77   public static void setArchiveEnabled(
78       Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) {
79     Assert.checkArgument(
80         VoicemailComponent.get(context).getVoicemailClient().isVoicemailArchiveAvailable(context));
81     new VisualVoicemailPreferences(context, phoneAccount)
82         .edit()
83         .putBoolean(ARCHIVE_ENABLED_KEY, isEnabled)
84         .apply();
85   }
86 
setVoicemailTranscriptionEnabled( Context context, PhoneAccountHandle phoneAccount, boolean isEnabled)87   public static void setVoicemailTranscriptionEnabled(
88       Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) {
89     Assert.checkArgument(
90         VoicemailComponent.get(context)
91             .getVoicemailClient()
92             .isVoicemailTranscriptionAvailable(context, phoneAccount));
93     new VisualVoicemailPreferences(context, phoneAccount)
94         .edit()
95         .putBoolean(TRANSCRIBE_VOICEMAILS_KEY, isEnabled)
96         .apply();
97 
98     if (!isEnabled) {
99       VvmLog.i(
100           "VisualVoicemailSettingsUtil.setVoicemailTranscriptionEnabled",
101           "clear all Google transcribed voicemail.");
102       DialerExecutorComponent.get(context)
103           .dialerExecutorFactory()
104           .createNonUiTaskBuilder(new ClearGoogleTranscribedVoicemailTranscriptionWorker(context))
105           .onSuccess(
106               (result) ->
107                   VvmLog.i(
108                       "VisualVoicemailSettingsUtil.setVoicemailTranscriptionEnabled",
109                       "voicemail transciptions cleared successfully"))
110           .onFailure(
111               (throwable) ->
112                   VvmLog.e(
113                       "VisualVoicemailSettingsUtil.setVoicemailTranscriptionEnabled",
114                       "unable to clear Google transcribed voicemails",
115                       throwable))
116           .build()
117           .executeParallel(null);
118     }
119   }
120 
setVoicemailDonationEnabled( Context context, PhoneAccountHandle phoneAccount, boolean isEnabled)121   public static void setVoicemailDonationEnabled(
122       Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) {
123     Assert.checkArgument(
124         VoicemailComponent.get(context)
125             .getVoicemailClient()
126             .isVoicemailTranscriptionAvailable(context, phoneAccount));
127     new VisualVoicemailPreferences(context, phoneAccount)
128         .edit()
129         .putBoolean(DONATE_VOICEMAILS_KEY, isEnabled)
130         .apply();
131   }
132 
isEnabled(Context context, PhoneAccountHandle phoneAccount)133   public static boolean isEnabled(Context context, PhoneAccountHandle phoneAccount) {
134     if (phoneAccount == null) {
135       LogUtil.i("VisualVoicemailSettingsUtil.isEnabled", "phone account is null");
136       return false;
137     }
138 
139     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
140     if (prefs.contains(IS_ENABLED_KEY)) {
141       // isEnableByDefault is a bit expensive, so don't use it as default value of
142       // getBoolean(). The "false" here should never be actually used.
143       return prefs.getBoolean(IS_ENABLED_KEY, false);
144     }
145     return new OmtpVvmCarrierConfigHelper(context, phoneAccount).isEnabledByDefault();
146   }
147 
isArchiveEnabled(Context context, PhoneAccountHandle phoneAccount)148   public static boolean isArchiveEnabled(Context context, PhoneAccountHandle phoneAccount) {
149     Assert.isNotNull(phoneAccount);
150 
151     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
152     return prefs.getBoolean(ARCHIVE_ENABLED_KEY, false);
153   }
154 
isVoicemailTranscriptionEnabled( Context context, PhoneAccountHandle phoneAccount)155   public static boolean isVoicemailTranscriptionEnabled(
156       Context context, PhoneAccountHandle phoneAccount) {
157     Assert.isNotNull(phoneAccount);
158 
159     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
160     return prefs.getBoolean(TRANSCRIBE_VOICEMAILS_KEY, false);
161   }
162 
isVoicemailDonationEnabled( Context context, PhoneAccountHandle phoneAccount)163   public static boolean isVoicemailDonationEnabled(
164       Context context, PhoneAccountHandle phoneAccount) {
165     Assert.isNotNull(phoneAccount);
166 
167     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
168     return prefs.getBoolean(DONATE_VOICEMAILS_KEY, false);
169   }
170 
171   /**
172    * Whether the client enabled status is explicitly set by user or by default(Whether carrier VVM
173    * app is installed). This is used to determine whether to disable the client when the carrier VVM
174    * app is installed. If the carrier VVM app is installed the client should give priority to it if
175    * the settings are not touched.
176    */
isEnabledUserSet(Context context, PhoneAccountHandle phoneAccount)177   public static boolean isEnabledUserSet(Context context, PhoneAccountHandle phoneAccount) {
178     if (phoneAccount == null) {
179       return false;
180     }
181     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
182     return prefs.contains(IS_ENABLED_KEY);
183   }
184 
185   /** Delete all the voicemails whose source_package field matches this package */
186   private static class VoicemailDeleteWorker implements Worker<Void, Void> {
187     private final Context context;
188 
VoicemailDeleteWorker(Context context)189     VoicemailDeleteWorker(Context context) {
190       this.context = context;
191     }
192 
193     @Override
doInBackground(Void unused)194     public Void doInBackground(Void unused) {
195       int deleted =
196           context
197               .getContentResolver()
198               .delete(Voicemails.buildSourceUri(context.getPackageName()), null, null);
199 
200       VvmLog.i("VisualVoicemailSettingsUtil.doInBackground", "deleted " + deleted + " voicemails");
201       return null;
202     }
203   }
204 
205   /**
206    * Clears all the voicemail transcripts in the call log whose source_package field matches this
207    * package
208    */
209   private static class ClearGoogleTranscribedVoicemailTranscriptionWorker
210       implements Worker<Void, Void> {
211     private final Context context;
212 
ClearGoogleTranscribedVoicemailTranscriptionWorker(Context context)213     ClearGoogleTranscribedVoicemailTranscriptionWorker(Context context) {
214       this.context = context;
215     }
216 
217     @Override
doInBackground(Void unused)218     public Void doInBackground(Void unused) {
219       ContentValues contentValues = new ContentValues();
220       contentValues.putNull(Voicemails.TRANSCRIPTION);
221       contentValues.put(
222           VoicemailCompat.TRANSCRIPTION_STATE, VoicemailCompat.TRANSCRIPTION_NOT_STARTED);
223 
224       Selection selection =
225           Selection.builder()
226               .and(Selection.column(CallLog.Calls.TYPE).is("=", Calls.VOICEMAIL_TYPE))
227               .and(Selection.column(Voicemails.SOURCE_PACKAGE).is("=", context.getPackageName()))
228               .build();
229 
230       int cleared =
231           context
232               .getContentResolver()
233               .update(
234                   Calls.CONTENT_URI_WITH_VOICEMAIL,
235                   contentValues,
236                   selection.getSelection(),
237                   selection.getSelectionArgs());
238 
239       VvmLog.i(
240           "VisualVoicemailSettingsUtil.doInBackground",
241           "cleared " + cleared + " voicemail transcription");
242       return null;
243     }
244   }
245 }
246