Home | History | Annotate | Download | only in impl
      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
     70   public VoicemailClientImpl() {
     71     Assert.checkArgument(BuildCompat.isAtLeastO());
     72   }
     73 
     74   @Override
     75   public boolean isVoicemailModuleEnabled() {
     76     return true;
     77   }
     78 
     79   @Override
     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
     86   public boolean isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
     87     return VisualVoicemailSettingsUtil.isEnabled(context, phoneAccountHandle);
     88   }
     89 
     90   @Override
     91   public void setVoicemailEnabled(
     92       Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {
     93     VisualVoicemailSettingsUtil.setEnabled(context, phoneAccountHandle, enabled);
     94   }
     95 
     96   @Override
     97   public boolean isVoicemailArchiveEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
     98     return VisualVoicemailSettingsUtil.isArchiveEnabled(context, phoneAccountHandle);
     99   }
    100 
    101   @Override
    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
    120   public void setVoicemailArchiveEnabled(
    121       Context context, PhoneAccountHandle phoneAccountHandle, boolean value) {
    122     VisualVoicemailSettingsUtil.setArchiveEnabled(context, phoneAccountHandle, value);
    123   }
    124 
    125   @Override
    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
    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
    160   public boolean isVoicemailDonationEnabled(Context context, PhoneAccountHandle account) {
    161     return isVoicemailTranscriptionAvailable(context)
    162         && VisualVoicemailSettingsUtil.isVoicemailDonationEnabled(context, account);
    163   }
    164 
    165   @Override
    166   public void setVoicemailDonationEnabled(
    167       Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {
    168     VisualVoicemailSettingsUtil.setVoicemailDonationEnabled(context, phoneAccountHandle, enabled);
    169   }
    170 
    171   @Override
    172   public boolean isActivated(Context context, PhoneAccountHandle phoneAccountHandle) {
    173     return VvmAccountManager.isAccountActivated(context, phoneAccountHandle);
    174   }
    175 
    176   @Override
    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
    184   public PersistableBundle getConfig(Context context, PhoneAccountHandle phoneAccountHandle) {
    185     return new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle).getConfig();
    186   }
    187 
    188   @Override
    189   @MainThread
    190   public void onBoot(@NonNull Context context) {
    191     OmtpService.onBoot(context);
    192     StatusCheckJobService.schedule(context);
    193   }
    194 
    195   @Override
    196   @MainThread
    197   public void onShutdown(@NonNull Context context) {
    198     OmtpService.onShutdown(context);
    199   }
    200 
    201   @Override
    202   public void addActivationStateListener(ActivationStateListener listener) {
    203     VvmAccountManager.addListener(listener);
    204   }
    205 
    206   @Override
    207   public void removeActivationStateListener(ActivationStateListener listener) {
    208     VvmAccountManager.removeListener(listener);
    209   }
    210 
    211   @Override
    212   public PinChanger createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle) {
    213     return new PinChangerImpl(context, phoneAccountHandle);
    214   }
    215 
    216   @TargetApi(VERSION_CODES.O)
    217   @Override
    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
    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
    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
    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
    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