Home | History | Annotate | Download | only in sync
      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.phone.vvm.omtp.sync;
     17 
     18 import android.annotation.CallSuper;
     19 import android.content.Context;
     20 import android.net.ConnectivityManager;
     21 import android.net.Network;
     22 import android.net.NetworkCapabilities;
     23 import android.net.NetworkRequest;
     24 import android.os.Handler;
     25 import android.os.Looper;
     26 import android.provider.VoicemailContract;
     27 import android.provider.VoicemailContract.Status;
     28 import android.telecom.PhoneAccountHandle;
     29 import android.util.Log;
     30 
     31 import com.android.phone.PhoneUtils;
     32 import com.android.phone.VoicemailUtils;
     33 import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
     34 
     35 /**
     36  * Base class for network request call backs for visual voicemail syncing with the Imap server. This
     37  * handles retries and network requests.
     38  */
     39 public abstract class VvmNetworkRequestCallback extends ConnectivityManager.NetworkCallback {
     40 
     41     private static final String TAG = "VvmNetworkRequest";
     42 
     43     // Timeout used to call ConnectivityManager.requestNetwork
     44     private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 60 * 1000;
     45 
     46     public static final String NETWORK_REQUEST_FAILED_TIMEOUT = "timeout";
     47     public static final String NETWORK_REQUEST_FAILED_LOST = "lost";
     48 
     49     protected Context mContext;
     50     protected PhoneAccountHandle mPhoneAccount;
     51     protected NetworkRequest mNetworkRequest;
     52     private ConnectivityManager mConnectivityManager;
     53     private final OmtpVvmCarrierConfigHelper mCarrierConfigHelper;
     54     private final int mSubId;
     55     private boolean mRequestSent = false;
     56     private boolean mResultReceived = false;
     57 
     58     public VvmNetworkRequestCallback(Context context, PhoneAccountHandle phoneAccount) {
     59         mContext = context;
     60         mPhoneAccount = phoneAccount;
     61         mSubId = PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount);
     62         mCarrierConfigHelper = new OmtpVvmCarrierConfigHelper(context, mSubId);
     63         mNetworkRequest = createNetworkRequest();
     64     }
     65 
     66     /**
     67      * @return NetworkRequest for a proper transport type. Use only cellular network if the carrier
     68      * requires it. Otherwise use whatever available.
     69      */
     70     private NetworkRequest createNetworkRequest() {
     71 
     72         NetworkRequest.Builder builder = new NetworkRequest.Builder()
     73                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
     74 
     75         if (mCarrierConfigHelper.isCellularDataRequired()) {
     76             Log.d(TAG, "Transport type: CELLULAR");
     77             builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
     78                     .setNetworkSpecifier(Integer.toString(mSubId));
     79         } else {
     80             Log.d(TAG, "Transport type: ANY");
     81         }
     82         return builder.build();
     83     }
     84 
     85     public NetworkRequest getNetworkRequest() {
     86         return mNetworkRequest;
     87     }
     88 
     89     @Override
     90     @CallSuper
     91     public void onLost(Network network) {
     92         Log.d(TAG, "onLost");
     93         mResultReceived = true;
     94         onFailed(NETWORK_REQUEST_FAILED_LOST);
     95     }
     96 
     97     @Override
     98     @CallSuper
     99     public void onAvailable(Network network) {
    100         super.onAvailable(network);
    101         mResultReceived = true;
    102     }
    103 
    104     @Override
    105     @CallSuper
    106     public void onUnavailable() {
    107         mResultReceived = true;
    108         onFailed(NETWORK_REQUEST_FAILED_TIMEOUT);
    109     }
    110 
    111     public void requestNetwork() {
    112         if (mRequestSent == true) {
    113             Log.e(TAG, "requestNetwork() called twice");
    114             return;
    115         }
    116         mRequestSent = true;
    117         getConnectivityManager().requestNetwork(getNetworkRequest(), this);
    118         /**
    119          * Somehow requestNetwork() with timeout doesn't work, and it's a hidden method.
    120          * Implement our own timeout mechanism instead.
    121          */
    122         Handler handler = new Handler(Looper.getMainLooper());
    123         handler.postDelayed(new Runnable() {
    124             @Override
    125             public void run() {
    126                 if (mResultReceived == false) {
    127                     onFailed(NETWORK_REQUEST_FAILED_TIMEOUT);
    128                 }
    129             }
    130         }, NETWORK_REQUEST_TIMEOUT_MILLIS);
    131     }
    132 
    133     public void releaseNetwork() {
    134         Log.d(TAG, "releaseNetwork");
    135         getConnectivityManager().unregisterNetworkCallback(this);
    136     }
    137 
    138     public ConnectivityManager getConnectivityManager() {
    139         if (mConnectivityManager == null) {
    140             mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
    141                     Context.CONNECTIVITY_SERVICE);
    142         }
    143         return mConnectivityManager;
    144     }
    145 
    146     @CallSuper
    147     public void onFailed(String reason) {
    148         Log.d(TAG, "onFailed: " + reason);
    149         if (mCarrierConfigHelper.isCellularDataRequired()) {
    150             VoicemailUtils.setDataChannelState(
    151                     mContext, mPhoneAccount,
    152                     Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED);
    153         } else {
    154             VoicemailUtils.setDataChannelState(
    155                     mContext, mPhoneAccount, Status.DATA_CHANNEL_STATE_NO_CONNECTION);
    156         }
    157         releaseNetwork();
    158     }
    159 }
    160