/* * 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; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; import android.util.Log; /** * {@hide} */ public abstract class DataConnection extends Handler { // the inherited class public enum State { ACTIVE, /* has active data connection */ ACTIVATING, /* during connecting process */ INACTIVE; /* has empty data connection */ public String toString() { switch (this) { case ACTIVE: return "active"; case ACTIVATING: return "setting up"; default: return "inactive"; } } public boolean isActive() { return this == ACTIVE; } public boolean isInactive() { return this == INACTIVE; } } public enum FailCause { NONE, OPERATOR_BARRED, INSUFFICIENT_RESOURCES, MISSING_UKNOWN_APN, UNKNOWN_PDP_ADDRESS, USER_AUTHENTICATION, ACTIVATION_REJECT_GGSN, ACTIVATION_REJECT_UNSPECIFIED, SERVICE_OPTION_NOT_SUPPORTED, SERVICE_OPTION_NOT_SUBSCRIBED, SERVICE_OPTION_OUT_OF_ORDER, NSAPI_IN_USE, PROTOCOL_ERRORS, REGISTRATION_FAIL, GPRS_REGISTRATION_FAIL, UNKNOWN, RADIO_NOT_AVAILABLE, RADIO_ERROR_RETRY; public boolean isPermanentFail() { return (this == OPERATOR_BARRED) || (this == MISSING_UKNOWN_APN) || (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) || (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) || (this == SERVICE_OPTION_NOT_SUPPORTED) || (this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == NSAPI_IN_USE) || (this == PROTOCOL_ERRORS); } public boolean isEventLoggable() { return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) || (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) || (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) || (this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == SERVICE_OPTION_NOT_SUPPORTED) || (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) || (this == PROTOCOL_ERRORS); } @Override public String toString() { switch (this) { case NONE: return "No Error"; case OPERATOR_BARRED: return "Operator Barred"; case INSUFFICIENT_RESOURCES: return "Insufficient Resources"; case MISSING_UKNOWN_APN: return "Missing / Unknown APN"; case UNKNOWN_PDP_ADDRESS: return "Unknown PDP Address"; case USER_AUTHENTICATION: return "Error User Autentication"; case ACTIVATION_REJECT_GGSN: return "Activation Reject GGSN"; case ACTIVATION_REJECT_UNSPECIFIED: return "Activation Reject unspecified"; case SERVICE_OPTION_NOT_SUPPORTED: return "Data Not Supported"; case SERVICE_OPTION_NOT_SUBSCRIBED: return "Data Not subscribed"; case SERVICE_OPTION_OUT_OF_ORDER: return "Data Services Out of Order"; case NSAPI_IN_USE: return "NSAPI in use"; case PROTOCOL_ERRORS: return "Protocol Errors"; case REGISTRATION_FAIL: return "Network Registration Failure"; case GPRS_REGISTRATION_FAIL: return "Data Network Registration Failure"; case RADIO_NOT_AVAILABLE: return "Radio Not Available"; case RADIO_ERROR_RETRY: return "Transient Radio Rrror"; default: return "Unknown Data Error"; } } } // ***** Event codes protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 1; protected static final int EVENT_GET_LAST_FAIL_DONE = 2; protected static final int EVENT_LINK_STATE_CHANGED = 3; protected static final int EVENT_DEACTIVATE_DONE = 4; protected static final int EVENT_FORCE_RETRY = 5; //***** Tag IDs for EventLog protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100; //***** Member Variables protected PhoneBase phone; protected Message onConnectCompleted; protected Message onDisconnect; protected int cid; protected String interfaceName; protected String ipAddress; protected String gatewayAddress; protected String[] dnsServers; protected State state; protected long createTime; protected long lastFailTime; protected FailCause lastFailCause; protected static final String NULL_IP = "0.0.0.0"; Object userData; // receivedDisconnectReq is set when disconnect during activation protected boolean receivedDisconnectReq; /* Instance Methods */ protected abstract void onSetupConnectionCompleted(AsyncResult ar); protected abstract void onDeactivated(AsyncResult ar); protected abstract void disconnect(Message msg); protected abstract void notifyFail(FailCause cause, Message onCompleted); protected abstract void notifyDisconnect(Message msg); protected abstract void onLinkStateChanged(DataLink.LinkState linkState); protected abstract FailCause getFailCauseFromRequest(int rilCause); public abstract String toString(); protected abstract void log(String s); //***** Constructor protected DataConnection(PhoneBase phone) { super(); this.phone = phone; onConnectCompleted = null; onDisconnect = null; this.cid = -1; receivedDisconnectReq = false; this.dnsServers = new String[2]; clearSettings(); } protected void setHttpProxy(String httpProxy, String httpPort) { if (httpProxy == null || httpProxy.length() == 0) { phone.setSystemProperty("net.gprs.http-proxy", null); return; } if (httpPort == null || httpPort.length() == 0) { httpPort = "8080"; // Default to port 8080 } phone.setSystemProperty("net.gprs.http-proxy", "http://" + httpProxy + ":" + httpPort + "/"); } public String getInterface() { return interfaceName; } public String getIpAddress() { return ipAddress; } public String getGatewayAddress() { return gatewayAddress; } public String[] getDnsServers() { return dnsServers; } public void clearSettings() { log("DataConnection.clearSettings()"); this.state = State.INACTIVE; this.createTime = -1; this.lastFailTime = -1; this.lastFailCause = FailCause.NONE; receivedDisconnectReq = false; onConnectCompleted = null; interfaceName = null; ipAddress = null; gatewayAddress = null; dnsServers[0] = null; dnsServers[1] = null; } protected void onGetLastFailCompleted(AsyncResult ar) { if (receivedDisconnectReq) { // Don't bother reporting the error if there's already a // pending disconnect request, since DataConnectionTracker // has already updated its state. notifyDisconnect(onDisconnect); } else { FailCause cause = FailCause.UNKNOWN; if (ar.exception == null) { int rilFailCause = ((int[]) (ar.result))[0]; cause = getFailCauseFromRequest(rilFailCause); } notifyFail(cause, onConnectCompleted); } } protected void onForceRetry() { if (receivedDisconnectReq) { notifyDisconnect(onDisconnect); } else { notifyFail(FailCause.RADIO_ERROR_RETRY, onConnectCompleted); } } @Override public void handleMessage(Message msg) { AsyncResult ar; log("DataConnection.handleMessage()"); switch (msg.what) { case EVENT_SETUP_DATA_CONNECTION_DONE: onSetupConnectionCompleted((AsyncResult) msg.obj); break; case EVENT_FORCE_RETRY: onForceRetry(); break; case EVENT_GET_LAST_FAIL_DONE: onGetLastFailCompleted((AsyncResult) msg.obj); break; case EVENT_LINK_STATE_CHANGED: ar = (AsyncResult) msg.obj; DataLink.LinkState ls = (DataLink.LinkState) ar.result; onLinkStateChanged(ls); break; case EVENT_DEACTIVATE_DONE: onDeactivated((AsyncResult) msg.obj); break; } } public State getState() { log("DataConnection.getState()"); return state; } public long getConnectionTime() { log("DataConnection.getConnectionTime()"); return createTime; } public long getLastFailTime() { log("DataConnection.getLastFailTime()"); return lastFailTime; } public FailCause getLastFailCause() { log("DataConnection.getLastFailCause()"); return lastFailCause; } }