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