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