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