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 */ 16package com.android.phone.vvm.omtp.sync; 17 18import android.annotation.CallSuper; 19import android.content.Context; 20import android.net.ConnectivityManager; 21import android.net.Network; 22import android.net.NetworkCapabilities; 23import android.net.NetworkRequest; 24import android.os.Handler; 25import android.os.Looper; 26import android.telecom.PhoneAccountHandle; 27import com.android.phone.PhoneUtils; 28import com.android.phone.VoicemailStatus; 29import com.android.phone.vvm.omtp.OmtpEvents; 30import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper; 31import 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 */ 37public 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