1 /* 2 * Copyright (C) 2006 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 17 package com.android.internal.telephony.dataconnection; 18 19 import android.app.PendingIntent; 20 import android.content.Context; 21 import android.net.NetworkConfig; 22 import android.telephony.Rlog; 23 24 import com.android.internal.R; 25 import com.android.internal.telephony.DctConstants; 26 import com.android.internal.telephony.Phone; 27 28 import java.io.FileDescriptor; 29 import java.io.PrintWriter; 30 import java.util.ArrayList; 31 import java.util.concurrent.atomic.AtomicBoolean; 32 import java.util.concurrent.atomic.AtomicInteger; 33 34 /** 35 * Maintain the Apn context 36 */ 37 public class ApnContext { 38 39 public final String LOG_TAG; 40 41 protected static final boolean DBG = false; 42 43 private final Context mContext; 44 45 private final String mApnType; 46 47 private DctConstants.State mState; 48 49 private ArrayList<ApnSetting> mWaitingApns = null; 50 51 public final int priority; 52 53 /** A zero indicates that all waiting APNs had a permanent error */ 54 private AtomicInteger mWaitingApnsPermanentFailureCountDown; 55 56 private ApnSetting mApnSetting; 57 58 DcAsyncChannel mDcAc; 59 60 String mReason; 61 62 PendingIntent mReconnectAlarmIntent; 63 64 /** 65 * user/app requested connection on this APN 66 */ 67 AtomicBoolean mDataEnabled; 68 69 private final Object mRefCountLock = new Object(); 70 private int mRefCount = 0; 71 72 /** 73 * carrier requirements met 74 */ 75 AtomicBoolean mDependencyMet; 76 77 private final DcTrackerBase mDcTracker; 78 79 public ApnContext(Context context, String apnType, String logTag, NetworkConfig config, 80 DcTrackerBase tracker) { 81 mContext = context; 82 mApnType = apnType; 83 mState = DctConstants.State.IDLE; 84 setReason(Phone.REASON_DATA_ENABLED); 85 mDataEnabled = new AtomicBoolean(false); 86 mDependencyMet = new AtomicBoolean(config.dependencyMet); 87 mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0); 88 priority = config.priority; 89 LOG_TAG = logTag; 90 mDcTracker = tracker; 91 } 92 93 public String getApnType() { 94 return mApnType; 95 } 96 97 public synchronized DcAsyncChannel getDcAc() { 98 return mDcAc; 99 } 100 101 public synchronized void setDataConnectionAc(DcAsyncChannel dcac) { 102 if (DBG) { 103 log("setDataConnectionAc: old dcac=" + mDcAc + " new dcac=" + dcac 104 + " this=" + this); 105 } 106 mDcAc = dcac; 107 } 108 109 public synchronized PendingIntent getReconnectIntent() { 110 return mReconnectAlarmIntent; 111 } 112 113 public synchronized void setReconnectIntent(PendingIntent intent) { 114 mReconnectAlarmIntent = intent; 115 } 116 117 public synchronized ApnSetting getApnSetting() { 118 log("getApnSetting: apnSetting=" + mApnSetting); 119 return mApnSetting; 120 } 121 122 public synchronized void setApnSetting(ApnSetting apnSetting) { 123 log("setApnSetting: apnSetting=" + apnSetting); 124 mApnSetting = apnSetting; 125 } 126 127 public synchronized void setWaitingApns(ArrayList<ApnSetting> waitingApns) { 128 mWaitingApns = waitingApns; 129 mWaitingApnsPermanentFailureCountDown.set(mWaitingApns.size()); 130 } 131 132 public int getWaitingApnsPermFailCount() { 133 return mWaitingApnsPermanentFailureCountDown.get(); 134 } 135 136 public void decWaitingApnsPermFailCount() { 137 mWaitingApnsPermanentFailureCountDown.decrementAndGet(); 138 } 139 140 public synchronized ApnSetting getNextWaitingApn() { 141 ArrayList<ApnSetting> list = mWaitingApns; 142 ApnSetting apn = null; 143 144 if (list != null) { 145 if (!list.isEmpty()) { 146 apn = list.get(0); 147 } 148 } 149 return apn; 150 } 151 152 public synchronized void removeWaitingApn(ApnSetting apn) { 153 if (mWaitingApns != null) { 154 mWaitingApns.remove(apn); 155 } 156 } 157 158 public synchronized ArrayList<ApnSetting> getWaitingApns() { 159 return mWaitingApns; 160 } 161 162 public synchronized void setState(DctConstants.State s) { 163 if (DBG) { 164 log("setState: " + s + ", previous state:" + mState); 165 } 166 167 mState = s; 168 169 if (mState == DctConstants.State.FAILED) { 170 if (mWaitingApns != null) { 171 mWaitingApns.clear(); // when teardown the connection and set to IDLE 172 } 173 } 174 } 175 176 public synchronized DctConstants.State getState() { 177 return mState; 178 } 179 180 public boolean isDisconnected() { 181 DctConstants.State currentState = getState(); 182 return ((currentState == DctConstants.State.IDLE) || 183 currentState == DctConstants.State.FAILED); 184 } 185 186 public synchronized void setReason(String reason) { 187 if (DBG) { 188 log("set reason as " + reason + ",current state " + mState); 189 } 190 mReason = reason; 191 } 192 193 public synchronized String getReason() { 194 return mReason; 195 } 196 197 public boolean isReady() { 198 return mDataEnabled.get() && mDependencyMet.get(); 199 } 200 201 public boolean isConnectable() { 202 return isReady() && ((mState == DctConstants.State.IDLE) 203 || (mState == DctConstants.State.SCANNING) 204 || (mState == DctConstants.State.RETRYING) 205 || (mState == DctConstants.State.FAILED)); 206 } 207 208 public boolean isConnectedOrConnecting() { 209 return isReady() && ((mState == DctConstants.State.CONNECTED) 210 || (mState == DctConstants.State.CONNECTING) 211 || (mState == DctConstants.State.SCANNING) 212 || (mState == DctConstants.State.RETRYING)); 213 } 214 215 public void setEnabled(boolean enabled) { 216 if (DBG) { 217 log("set enabled as " + enabled + ", current state is " + mDataEnabled.get()); 218 } 219 mDataEnabled.set(enabled); 220 } 221 222 public boolean isEnabled() { 223 return mDataEnabled.get(); 224 } 225 226 public void setDependencyMet(boolean met) { 227 if (DBG) { 228 log("set mDependencyMet as " + met + " current state is " + mDependencyMet.get()); 229 } 230 mDependencyMet.set(met); 231 } 232 233 public boolean getDependencyMet() { 234 return mDependencyMet.get(); 235 } 236 237 public boolean isProvisioningApn() { 238 String provisioningApn = mContext.getResources() 239 .getString(R.string.mobile_provisioning_apn); 240 if ((mApnSetting != null) && (mApnSetting.apn != null)) { 241 return (mApnSetting.apn.equals(provisioningApn)); 242 } else { 243 return false; 244 } 245 } 246 247 public void incRefCount() { 248 synchronized (mRefCountLock) { 249 if (mRefCount++ == 0) { 250 mDcTracker.setEnabled(mDcTracker.apnTypeToId(mApnType), true); 251 } 252 } 253 } 254 255 public void decRefCount() { 256 synchronized (mRefCountLock) { 257 if (mRefCount-- == 1) { 258 mDcTracker.setEnabled(mDcTracker.apnTypeToId(mApnType), false); 259 } 260 } 261 } 262 263 @Override 264 public synchronized String toString() { 265 // We don't print mDataConnection because its recursive. 266 return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns={" + mWaitingApns + 267 "} mWaitingApnsPermanentFailureCountDown=" + mWaitingApnsPermanentFailureCountDown + 268 " mApnSetting={" + mApnSetting + "} mReason=" + mReason + 269 " mDataEnabled=" + mDataEnabled + " mDependencyMet=" + mDependencyMet + "}"; 270 } 271 272 protected void log(String s) { 273 Rlog.d(LOG_TAG, "[ApnContext:" + mApnType + "] " + s); 274 } 275 276 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 277 pw.println("ApnContext: " + this.toString()); 278 } 279 } 280