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.os.AsyncResult;
20import android.os.Handler;
21import android.os.Message;
22import android.util.Log;
23
24/**
25 * {@hide}
26 */
27public abstract class DataConnection extends Handler {
28
29    // the inherited class
30
31    public enum State {
32        ACTIVE, /* has active data connection */
33        ACTIVATING, /* during connecting process */
34        INACTIVE; /* has empty data connection */
35
36        public String toString() {
37            switch (this) {
38            case ACTIVE:
39                return "active";
40            case ACTIVATING:
41                return "setting up";
42            default:
43                return "inactive";
44            }
45        }
46
47        public boolean isActive() {
48            return this == ACTIVE;
49        }
50
51        public boolean isInactive() {
52            return this == INACTIVE;
53        }
54    }
55
56    public enum FailCause {
57        NONE,
58        OPERATOR_BARRED,
59        INSUFFICIENT_RESOURCES,
60        MISSING_UKNOWN_APN,
61        UNKNOWN_PDP_ADDRESS,
62        USER_AUTHENTICATION,
63        ACTIVATION_REJECT_GGSN,
64        ACTIVATION_REJECT_UNSPECIFIED,
65        SERVICE_OPTION_NOT_SUPPORTED,
66        SERVICE_OPTION_NOT_SUBSCRIBED,
67        SERVICE_OPTION_OUT_OF_ORDER,
68        NSAPI_IN_USE,
69        PROTOCOL_ERRORS,
70        REGISTRATION_FAIL,
71        GPRS_REGISTRATION_FAIL,
72        UNKNOWN,
73
74        RADIO_NOT_AVAILABLE,
75        RADIO_ERROR_RETRY;
76
77        public boolean isPermanentFail() {
78            return (this == OPERATOR_BARRED) || (this == MISSING_UKNOWN_APN) ||
79                   (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) ||
80                   (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
81                   (this == SERVICE_OPTION_NOT_SUPPORTED) ||
82                   (this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == NSAPI_IN_USE) ||
83                   (this == PROTOCOL_ERRORS);
84        }
85
86        public boolean isEventLoggable() {
87            return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
88                    (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) ||
89                    (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
90                    (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
91                    (this == SERVICE_OPTION_NOT_SUPPORTED) ||
92                    (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
93                    (this == PROTOCOL_ERRORS);
94        }
95
96        @Override
97        public String toString() {
98            switch (this) {
99            case NONE:
100                return "No Error";
101            case OPERATOR_BARRED:
102                return "Operator Barred";
103            case INSUFFICIENT_RESOURCES:
104                return "Insufficient Resources";
105            case MISSING_UKNOWN_APN:
106                return "Missing / Unknown APN";
107            case UNKNOWN_PDP_ADDRESS:
108                return "Unknown PDP Address";
109            case USER_AUTHENTICATION:
110                return "Error User Autentication";
111            case ACTIVATION_REJECT_GGSN:
112                return "Activation Reject GGSN";
113            case ACTIVATION_REJECT_UNSPECIFIED:
114                return "Activation Reject unspecified";
115            case SERVICE_OPTION_NOT_SUPPORTED:
116                return "Data Not Supported";
117            case SERVICE_OPTION_NOT_SUBSCRIBED:
118                return "Data Not subscribed";
119            case SERVICE_OPTION_OUT_OF_ORDER:
120                return "Data Services Out of Order";
121            case NSAPI_IN_USE:
122                return "NSAPI in use";
123            case PROTOCOL_ERRORS:
124                return "Protocol Errors";
125            case REGISTRATION_FAIL:
126                return "Network Registration Failure";
127            case GPRS_REGISTRATION_FAIL:
128                return "Data Network Registration Failure";
129            case RADIO_NOT_AVAILABLE:
130                return "Radio Not Available";
131            case RADIO_ERROR_RETRY:
132                return "Transient Radio Rrror";
133            default:
134                return "Unknown Data Error";
135            }
136        }
137    }
138
139    // ***** Event codes
140    protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 1;
141    protected static final int EVENT_GET_LAST_FAIL_DONE = 2;
142    protected static final int EVENT_LINK_STATE_CHANGED = 3;
143    protected static final int EVENT_DEACTIVATE_DONE = 4;
144    protected static final int EVENT_FORCE_RETRY = 5;
145
146    //***** Tag IDs for EventLog
147    protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
148
149
150    //***** Member Variables
151    protected PhoneBase phone;
152    protected Message onConnectCompleted;
153    protected Message onDisconnect;
154    protected int cid;
155    protected String interfaceName;
156    protected String ipAddress;
157    protected String gatewayAddress;
158    protected String[] dnsServers;
159    protected State state;
160    protected long createTime;
161    protected long lastFailTime;
162    protected FailCause lastFailCause;
163    protected static final String NULL_IP = "0.0.0.0";
164    Object userData;
165
166    // receivedDisconnectReq is set when disconnect during activation
167    protected boolean receivedDisconnectReq;
168
169    /* Instance Methods */
170    protected abstract void onSetupConnectionCompleted(AsyncResult ar);
171
172    protected abstract void onDeactivated(AsyncResult ar);
173
174    protected abstract void disconnect(Message msg);
175
176    protected abstract void notifyFail(FailCause cause, Message onCompleted);
177
178    protected abstract void notifyDisconnect(Message msg);
179
180    protected abstract void onLinkStateChanged(DataLink.LinkState linkState);
181
182    protected abstract FailCause getFailCauseFromRequest(int rilCause);
183
184    public abstract String toString();
185
186    protected abstract void log(String s);
187
188
189   //***** Constructor
190    protected DataConnection(PhoneBase phone) {
191        super();
192        this.phone = phone;
193        onConnectCompleted = null;
194        onDisconnect = null;
195        this.cid = -1;
196        receivedDisconnectReq = false;
197        this.dnsServers = new String[2];
198
199        clearSettings();
200    }
201
202    protected void setHttpProxy(String httpProxy, String httpPort) {
203        if (httpProxy == null || httpProxy.length() == 0) {
204            phone.setSystemProperty("net.gprs.http-proxy", null);
205            return;
206        }
207
208        if (httpPort == null || httpPort.length() == 0) {
209            httpPort = "8080";     // Default to port 8080
210        }
211
212        phone.setSystemProperty("net.gprs.http-proxy",
213                "http://" + httpProxy + ":" + httpPort + "/");
214    }
215
216    public String getInterface() {
217        return interfaceName;
218    }
219
220    public String getIpAddress() {
221        return ipAddress;
222    }
223
224    public String getGatewayAddress() {
225        return gatewayAddress;
226    }
227
228    public String[] getDnsServers() {
229        return dnsServers;
230    }
231
232    public void clearSettings() {
233        log("DataConnection.clearSettings()");
234
235        this.state = State.INACTIVE;
236        this.createTime = -1;
237        this.lastFailTime = -1;
238        this.lastFailCause = FailCause.NONE;
239
240        receivedDisconnectReq = false;
241        onConnectCompleted = null;
242        interfaceName = null;
243        ipAddress = null;
244        gatewayAddress = null;
245        dnsServers[0] = null;
246        dnsServers[1] = null;
247    }
248
249    protected void onGetLastFailCompleted(AsyncResult ar) {
250        if (receivedDisconnectReq) {
251            // Don't bother reporting the error if there's already a
252            // pending disconnect request, since DataConnectionTracker
253            // has already updated its state.
254            notifyDisconnect(onDisconnect);
255        } else {
256            FailCause cause = FailCause.UNKNOWN;
257
258            if (ar.exception == null) {
259                int rilFailCause = ((int[]) (ar.result))[0];
260                cause = getFailCauseFromRequest(rilFailCause);
261            }
262            notifyFail(cause, onConnectCompleted);
263        }
264    }
265
266    protected void onForceRetry() {
267        if (receivedDisconnectReq) {
268            notifyDisconnect(onDisconnect);
269        } else {
270            notifyFail(FailCause.RADIO_ERROR_RETRY, onConnectCompleted);
271        }
272    }
273
274    @Override
275    public void handleMessage(Message msg) {
276        AsyncResult ar;
277
278        log("DataConnection.handleMessage()");
279
280        switch (msg.what) {
281
282        case EVENT_SETUP_DATA_CONNECTION_DONE:
283            onSetupConnectionCompleted((AsyncResult) msg.obj);
284            break;
285
286        case EVENT_FORCE_RETRY:
287            onForceRetry();
288            break;
289
290        case EVENT_GET_LAST_FAIL_DONE:
291            onGetLastFailCompleted((AsyncResult) msg.obj);
292            break;
293
294        case EVENT_LINK_STATE_CHANGED:
295            ar = (AsyncResult) msg.obj;
296            DataLink.LinkState ls  = (DataLink.LinkState) ar.result;
297            onLinkStateChanged(ls);
298            break;
299
300        case EVENT_DEACTIVATE_DONE:
301            onDeactivated((AsyncResult) msg.obj);
302            break;
303        }
304    }
305
306    public State getState() {
307        log("DataConnection.getState()");
308        return state;
309    }
310
311    public long getConnectionTime() {
312        log("DataConnection.getConnectionTime()");
313        return createTime;
314    }
315
316    public long getLastFailTime() {
317        log("DataConnection.getLastFailTime()");
318        return lastFailTime;
319    }
320
321    public FailCause getLastFailCause() {
322        log("DataConnection.getLastFailCause()");
323        return lastFailCause;
324    }
325}
326