/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony.dataconnection; import android.app.PendingIntent; import android.telephony.Rlog; import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.Phone; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** * Maintain the Apn context */ public class ApnContext { public final String LOG_TAG; protected static final boolean DBG = false; private final String mApnType; private DctConstants.State mState; private ArrayList mWaitingApns = null; /** A zero indicates that all waiting APNs had a permanent error */ private AtomicInteger mWaitingApnsPermanentFailureCountDown; private ApnSetting mApnSetting; DataConnectionAc mDataConnectionAc; String mReason; PendingIntent mReconnectAlarmIntent; /** * user/app requested connection on this APN */ AtomicBoolean mDataEnabled; /** * carrier requirements met */ AtomicBoolean mDependencyMet; public ApnContext(String apnType, String logTag) { mApnType = apnType; mState = DctConstants.State.IDLE; setReason(Phone.REASON_DATA_ENABLED); mDataEnabled = new AtomicBoolean(false); mDependencyMet = new AtomicBoolean(true); mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0); LOG_TAG = logTag; } public String getApnType() { return mApnType; } public synchronized DataConnectionAc getDcAc() { return mDataConnectionAc; } public synchronized void setDataConnectionAc(DataConnectionAc dcac) { if (DBG) { log("setDataConnectionAc: old dcac=" + mDataConnectionAc + " new dcac=" + dcac + " this=" + this); } if ((dcac == null) && (mDataConnectionAc != null)) { // TODO: This tearDown should be done by caller, but for now we'll do it if (DBG) log("setDataConnection: call tearDown"); mDataConnectionAc.tearDown(this, "", null); } mDataConnectionAc = dcac; } public synchronized PendingIntent getReconnectIntent() { return mReconnectAlarmIntent; } public synchronized void setReconnectIntent(PendingIntent intent) { mReconnectAlarmIntent = intent; } public synchronized ApnSetting getApnSetting() { log("getApnSetting: apnSetting=" + mApnSetting); return mApnSetting; } public synchronized void setApnSetting(ApnSetting apnSetting) { log("setApnSetting: apnSetting=" + apnSetting); mApnSetting = apnSetting; } public synchronized void setWaitingApns(ArrayList waitingApns) { mWaitingApns = waitingApns; mWaitingApnsPermanentFailureCountDown.set(mWaitingApns.size()); } public int getWaitingApnsPermFailCount() { return mWaitingApnsPermanentFailureCountDown.get(); } public void decWaitingApnsPermFailCount() { mWaitingApnsPermanentFailureCountDown.decrementAndGet(); } public synchronized ApnSetting getNextWaitingApn() { ArrayList list = mWaitingApns; ApnSetting apn = null; if (list != null) { if (!list.isEmpty()) { apn = list.get(0); } } return apn; } public synchronized void removeWaitingApn(ApnSetting apn) { if (mWaitingApns != null) { mWaitingApns.remove(apn); } } public synchronized ArrayList getWaitingApns() { return mWaitingApns; } public synchronized void setState(DctConstants.State s) { if (DBG) { log("setState: " + s + ", previous state:" + mState); } mState = s; if (mState == DctConstants.State.FAILED) { if (mWaitingApns != null) { mWaitingApns.clear(); // when teardown the connection and set to IDLE } } } public synchronized DctConstants.State getState() { return mState; } public boolean isDisconnected() { DctConstants.State currentState = getState(); return ((currentState == DctConstants.State.IDLE) || currentState == DctConstants.State.FAILED); } public synchronized void setReason(String reason) { if (DBG) { log("set reason as " + reason + ",current state " + mState); } mReason = reason; } public synchronized String getReason() { return mReason; } public boolean isReady() { return mDataEnabled.get() && mDependencyMet.get(); } public boolean isConnectable() { return isReady() && ((mState == DctConstants.State.IDLE) || (mState == DctConstants.State.SCANNING) || (mState == DctConstants.State.RETRYING) || (mState == DctConstants.State.FAILED)); } public void setEnabled(boolean enabled) { if (DBG) { log("set enabled as " + enabled + ", current state is " + mDataEnabled.get()); } mDataEnabled.set(enabled); } public boolean isEnabled() { return mDataEnabled.get(); } public void setDependencyMet(boolean met) { if (DBG) { log("set mDependencyMet as " + met + " current state is " + mDependencyMet.get()); } mDependencyMet.set(met); } public boolean getDependencyMet() { return mDependencyMet.get(); } @Override public String toString() { // We don't print mDataConnection because its recursive. return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns={" + mWaitingApns + "} mWaitingApnsPermanentFailureCountDown=" + mWaitingApnsPermanentFailureCountDown + " mApnSetting={" + mApnSetting + "} mReason=" + mReason + " mDataEnabled=" + mDataEnabled + " mDependencyMet=" + mDependencyMet + "}"; } protected void log(String s) { Rlog.d(LOG_TAG, "[ApnContext:" + mApnType + "] " + s); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("ApnContext: " + this.toString()); } }