The RIL call LAST_PDP_FAIL_CAUSE, gives us the PDP setup failure cause. Add support for retry based on these causes.
326 lines
9.9 KiB
Java
326 lines
9.9 KiB
Java
/*
|
|
* 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;
|
|
}
|
|
}
|