Merge "Remove REPORT_EVENT_CONTEXT_HUB gscan option" into mm-wireless-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e9fa13..a03f328 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21106,6 +21106,7 @@
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
+ method public boolean setMetered(int, boolean);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index c9efc69..cd237c1 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -27,9 +27,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.net.DhcpResults;
import android.net.BaseDhcpStateMachine;
-import android.net.DhcpStateMachine;
+import android.net.DhcpResults;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.NetworkUtils;
@@ -105,12 +104,35 @@
// t=0, t=2, t=6, t=14, t=30, allowing for 10% jitter.
private static final int DHCP_TIMEOUT_MS = 36 * SECONDS;
+ private static final int PUBLIC_BASE = Protocol.BASE_DHCP;
+
+ /* Commands from controller to start/stop DHCP */
+ public static final int CMD_START_DHCP = PUBLIC_BASE + 1;
+ public static final int CMD_STOP_DHCP = PUBLIC_BASE + 2;
+ public static final int CMD_RENEW_DHCP = PUBLIC_BASE + 3;
+
+ /* Notification from DHCP state machine prior to DHCP discovery/renewal */
+ public static final int CMD_PRE_DHCP_ACTION = PUBLIC_BASE + 4;
+ /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates
+ * success/failure */
+ public static final int CMD_POST_DHCP_ACTION = PUBLIC_BASE + 5;
+ /* Notification from DHCP state machine before quitting */
+ public static final int CMD_ON_QUIT = PUBLIC_BASE + 6;
+
+ /* Command from controller to indicate DHCP discovery/renewal can continue
+ * after pre DHCP action is complete */
+ public static final int CMD_PRE_DHCP_ACTION_COMPLETE = PUBLIC_BASE + 7;
+
+ /* Message.arg1 arguments to CMD_POST_DHCP notification */
+ public static final int DHCP_SUCCESS = 1;
+ public static final int DHCP_FAILURE = 2;
+
// Messages.
- private static final int BASE = Protocol.BASE_DHCP + 100;
- private static final int CMD_KICK = BASE + 1;
- private static final int CMD_RECEIVED_PACKET = BASE + 2;
- private static final int CMD_TIMEOUT = BASE + 3;
- private static final int CMD_ONESHOT_TIMEOUT = BASE + 4;
+ private static final int PRIVATE_BASE = Protocol.BASE_DHCP + 100;
+ private static final int CMD_KICK = PRIVATE_BASE + 1;
+ private static final int CMD_RECEIVED_PACKET = PRIVATE_BASE + 2;
+ private static final int CMD_TIMEOUT = PRIVATE_BASE + 3;
+ private static final int CMD_ONESHOT_TIMEOUT = PRIVATE_BASE + 4;
// DHCP parameters that we request.
private static final byte[] REQUESTED_PARAMS = new byte[] {
@@ -210,7 +232,7 @@
// Used to time out PacketRetransmittingStates.
mTimeoutIntent = createStateMachineCommandIntent("TIMEOUT", CMD_TIMEOUT);
// Used to schedule DHCP renews.
- mRenewIntent = createStateMachineCommandIntent("RENEW", DhcpStateMachine.CMD_RENEW_DHCP);
+ mRenewIntent = createStateMachineCommandIntent("RENEW", CMD_RENEW_DHCP);
// Used to tell the caller when its request (CMD_START_DHCP or CMD_RENEW_DHCP) timed out.
// TODO: when the legacy DHCP client is gone, make the client fully asynchronous and
// remove this.
@@ -225,6 +247,11 @@
public static BaseDhcpStateMachine makeDhcpStateMachine(
Context context, StateMachine controller, String intf) {
+ return makeDhcpClient(context, controller, intf);
+ }
+
+ public static DhcpClient makeDhcpClient(
+ Context context, StateMachine controller, String intf) {
DhcpClient client = new DhcpClient(context, controller, intf);
client.start();
return client;
@@ -437,13 +464,12 @@
}
private void notifySuccess() {
- mController.sendMessage(DhcpStateMachine.CMD_POST_DHCP_ACTION,
- DhcpStateMachine.DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease));
+ mController.sendMessage(
+ CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease));
}
private void notifyFailure() {
- mController.sendMessage(DhcpStateMachine.CMD_POST_DHCP_ACTION,
- DhcpStateMachine.DHCP_FAILURE, 0, null);
+ mController.sendMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0, null);
}
private void clearDhcpState() {
@@ -465,7 +491,7 @@
protected void onQuitting() {
Log.d(TAG, "onQuitting");
- mController.sendMessage(DhcpStateMachine.CMD_ON_QUIT);
+ mController.sendMessage(CMD_ON_QUIT);
}
private void maybeLog(String msg) {
@@ -479,17 +505,17 @@
private String messageName(int what) {
switch (what) {
- case DhcpStateMachine.CMD_START_DHCP:
+ case CMD_START_DHCP:
return "CMD_START_DHCP";
- case DhcpStateMachine.CMD_STOP_DHCP:
+ case CMD_STOP_DHCP:
return "CMD_STOP_DHCP";
- case DhcpStateMachine.CMD_RENEW_DHCP:
+ case CMD_RENEW_DHCP:
return "CMD_RENEW_DHCP";
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ case CMD_PRE_DHCP_ACTION:
return "CMD_PRE_DHCP_ACTION";
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE:
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
return "CMD_PRE_DHCP_ACTION_COMPLETE";
- case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ case CMD_POST_DHCP_ACTION:
return "CMD_POST_DHCP_ACTION";
case CMD_KICK:
return "CMD_KICK";
@@ -532,14 +558,14 @@
@Override
public void enter() {
super.enter();
- mController.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION);
+ mController.sendMessage(CMD_PRE_DHCP_ACTION);
}
@Override
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE:
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
transitionTo(mOtherState);
return HANDLED;
default:
@@ -574,7 +600,7 @@
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
- case DhcpStateMachine.CMD_START_DHCP:
+ case CMD_START_DHCP:
scheduleOneshotTimeout();
if (mRegisteredForPreDhcpNotification) {
transitionTo(mWaitBeforeStartState);
@@ -630,7 +656,7 @@
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
- case DhcpStateMachine.CMD_STOP_DHCP:
+ case CMD_STOP_DHCP:
transitionTo(mStoppedState);
return HANDLED;
case CMD_ONESHOT_TIMEOUT:
@@ -845,7 +871,7 @@
super.enter();
cancelOneshotTimeout();
notifySuccess();
- // TODO: DhcpStateMachine only supports renewing at 50% of the lease time, and does not
+ // TODO: DhcpStateMachine only supported renewing at 50% of the lease time, and did not
// support rebinding. Once the legacy DHCP client is gone, fix this.
scheduleRenew();
}
@@ -854,7 +880,7 @@
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
- case DhcpStateMachine.CMD_RENEW_DHCP:
+ case CMD_RENEW_DHCP:
if (mRegisteredForPreDhcpNotification) {
transitionTo(mWaitBeforeRenewalState);
} else {
@@ -908,7 +934,7 @@
}
}
- // Not implemented. DhcpStateMachine does not implement it either.
+ // Not implemented. DhcpStateMachine did not implement it either.
class DhcpRebindingState extends LoggingState {
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 06b6ee7..d0d87b1 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -17,9 +17,7 @@
package android.net.ip;
import android.content.Context;
-import android.net.BaseDhcpStateMachine;
import android.net.DhcpResults;
-import android.net.DhcpStateMachine;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -31,7 +29,6 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -61,44 +58,29 @@
* @hide
*/
public class IpManager extends StateMachine {
- private static final String TAG = IpManager.class.getSimpleName();
private static final boolean DBG = true;
private static final boolean VDBG = false;
/**
- * Callbacks for both configuration of IpManager and for handling
- * events as desired.
+ * Callbacks for handling IpManager events.
*/
public static class Callback {
- /**
- * Configuration callbacks.
- *
- * Override methods as desired in order to control which features
- * IpManager will use at run time.
- */
-
- // An IpReachabilityMonitor will always be started, if only for logging.
- // This method is checked before probing neighbors and before calling
- // onProvisioningLost() (see below).
- public boolean usingIpReachabilityMonitor() {
- return false;
- }
-
- /**
- * Event callbacks.
- *
- * Override methods as desired in order to handle event callbacks
- * as IpManager invokes them.
- */
-
- // Implementations must call IpManager#completedPreDhcpAction().
+ // In order to receive onPreDhcpAction(), call #withPreDhcpAction()
+ // when constructing a ProvisioningConfiguration.
+ //
+ // Implementations of onPreDhcpAction() must call
+ // IpManager#completedPreDhcpAction() to indicate that DHCP is clear
+ // to proceed.
public void onPreDhcpAction() {}
public void onPostDhcpAction() {}
- // TODO: Kill with fire once DHCP and static configuration are moved
- // out of WifiStateMachine.
- public void onIPv4ProvisioningSuccess(DhcpResults dhcpResults) {}
- public void onIPv4ProvisioningFailure() {}
+ // This is purely advisory and not an indication of provisioning
+ // success or failure. This is only here for callers that want to
+ // expose DHCPv4 results to other APIs (e.g., WifiInfo#setInetAddress).
+ // DHCPv4 or static IPv4 configuration failure or success can be
+ // determined by whether or not the passed-in DhcpResults object is
+ // null or not.
+ public void onNewDhcpResults(DhcpResults dhcpResults) {}
public void onProvisioningSuccess(LinkProperties newLp) {}
public void onProvisioningFailure(LinkProperties newLp) {}
@@ -109,6 +91,67 @@
// Called when the internal IpReachabilityMonitor (if enabled) has
// detected the loss of a critical number of required neighbors.
public void onReachabilityLost(String logMsg) {}
+
+ // Called when the IpManager state machine terminates.
+ public void onQuit() {}
+ }
+
+ /**
+ * This class encapsulates parameters to be passed to
+ * IpManager#startProvisioning(). A defensive copy is made by IpManager
+ * and the values specified herein are in force until IpManager#stop()
+ * is called.
+ *
+ * Example use:
+ *
+ * final ProvisioningConfiguration config =
+ * mIpManager.buildProvisioningConfiguration()
+ * .withPreDhcpAction()
+ * .build();
+ * mIpManager.startProvisioning(config);
+ * ...
+ * mIpManager.stop();
+ *
+ * The specified provisioning configuration will only be active until
+ * IpManager#stop() is called. Future calls to IpManager#startProvisioning()
+ * must specify the configuration again.
+ */
+ public static class ProvisioningConfiguration {
+
+ public static class Builder {
+ private ProvisioningConfiguration mConfig = new ProvisioningConfiguration();
+
+ public Builder withoutIpReachabilityMonitor() {
+ mConfig.mUsingIpReachabilityMonitor = false;
+ return this;
+ }
+
+ public Builder withPreDhcpAction() {
+ mConfig.mRequestedPreDhcpAction = true;
+ return this;
+ }
+
+ public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) {
+ mConfig.mStaticIpConfig = staticConfig;
+ return this;
+ }
+
+ public ProvisioningConfiguration build() {
+ return new ProvisioningConfiguration(mConfig);
+ }
+ }
+
+ /* package */ boolean mUsingIpReachabilityMonitor = true;
+ /* package */ boolean mRequestedPreDhcpAction;
+ /* package */ StaticIpConfiguration mStaticIpConfig;
+
+ public ProvisioningConfiguration() {}
+
+ public ProvisioningConfiguration(ProvisioningConfiguration other) {
+ mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor;
+ mRequestedPreDhcpAction = other.mRequestedPreDhcpAction;
+ mStaticIpConfig = other.mStaticIpConfig;
+ }
}
private static final int CMD_STOP = 1;
@@ -122,8 +165,10 @@
private final Object mLock = new Object();
private final State mStoppedState = new StoppedState();
+ private final State mStoppingState = new StoppingState();
private final State mStartedState = new StartedState();
+ private final String mTag;
private final Context mContext;
private final String mInterfaceName;
@VisibleForTesting
@@ -137,9 +182,9 @@
* Non-final member variables accessed only from within our StateMachine.
*/
private IpReachabilityMonitor mIpReachabilityMonitor;
- private BaseDhcpStateMachine mDhcpStateMachine;
+ private DhcpClient mDhcpClient;
private DhcpResults mDhcpResults;
- private StaticIpConfiguration mStaticIpConfig;
+ private ProvisioningConfiguration mConfiguration;
/**
* Member variables accessed both from within the StateMachine thread
@@ -150,11 +195,11 @@
public IpManager(Context context, String ifName, Callback callback)
throws IllegalArgumentException {
- super(TAG + "." + ifName);
+ super(IpManager.class.getSimpleName() + "." + ifName);
+ mTag = getName();
mContext = context;
mInterfaceName = ifName;
-
mCallback = callback;
mNwService = INetworkManagementService.Stub.asInterface(
@@ -171,7 +216,7 @@
try {
mNwService.registerObserver(mNetlinkTracker);
} catch (RemoteException e) {
- Log.e(TAG, "Couldn't register NetlinkTracker: " + e.toString());
+ Log.e(mTag, "Couldn't register NetlinkTracker: " + e.toString());
}
resetLinkProperties();
@@ -179,6 +224,8 @@
// Super simple StateMachine.
addState(mStoppedState);
addState(mStartedState);
+ addState(mStoppingState);
+
setInitialState(mStoppedState);
setLogRecSize(MAX_LOG_RECORDS);
super.start();
@@ -192,7 +239,9 @@
*/
@VisibleForTesting
protected IpManager(String ifName, Callback callback) {
- super(TAG + ".test-" + ifName);
+ super(IpManager.class.getSimpleName() + ".test-" + ifName);
+ mTag = getName();
+
mInterfaceName = ifName;
mCallback = callback;
@@ -201,16 +250,35 @@
mNetlinkTracker = null;
}
- public void startProvisioning(StaticIpConfiguration staticIpConfig) {
- getInterfaceIndex();
+ @Override
+ protected void onQuitting() {
+ mCallback.onQuit();
+ }
- sendMessage(CMD_START, staticIpConfig);
+ // Shut down this IpManager instance altogether.
+ public void shutdown() {
+ stop();
+ quit();
+ }
+
+ public static ProvisioningConfiguration.Builder buildProvisioningConfiguration() {
+ return new ProvisioningConfiguration.Builder();
+ }
+
+ public void startProvisioning(ProvisioningConfiguration req) {
+ getInterfaceIndex();
+ sendMessage(CMD_START, new ProvisioningConfiguration(req));
+ }
+
+ // TODO: Delete this.
+ public void startProvisioning(StaticIpConfiguration staticIpConfig) {
+ startProvisioning(buildProvisioningConfiguration()
+ .withStaticConfiguration(staticIpConfig)
+ .build());
}
public void startProvisioning() {
- getInterfaceIndex();
-
- sendMessage(CMD_START);
+ startProvisioning(new ProvisioningConfiguration());
}
public void stop() {
@@ -236,12 +304,48 @@
* Internals.
*/
+ @Override
+ protected String getWhatToString(int what) {
+ // TODO: Investigate switching to reflection.
+ switch (what) {
+ case CMD_STOP:
+ return "CMD_STOP";
+ case CMD_START:
+ return "CMD_START";
+ case CMD_CONFIRM:
+ return "CMD_CONFIRM";
+ case EVENT_PRE_DHCP_ACTION_COMPLETE:
+ return "EVENT_PRE_DHCP_ACTION_COMPLETE";
+ case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+ return "EVENT_NETLINK_LINKPROPERTIES_CHANGED";
+ case DhcpClient.CMD_PRE_DHCP_ACTION:
+ return "DhcpClient.CMD_PRE_DHCP_ACTION";
+ case DhcpClient.CMD_POST_DHCP_ACTION:
+ return "DhcpClient.CMD_POST_DHCP_ACTION";
+ case DhcpClient.CMD_ON_QUIT:
+ return "DhcpClient.CMD_ON_QUIT";
+ }
+ return "UNKNOWN:" + Integer.toString(what);
+ }
+
+ @Override
+ protected String getLogRecString(Message msg) {
+ final String logLine = String.format(
+ "iface{%s/%d} arg1{%d} arg2{%d} obj{%s}",
+ mInterfaceName, mInterfaceIndex,
+ msg.arg1, msg.arg2, Objects.toString(msg.obj));
+ if (VDBG) {
+ Log.d(mTag, getWhatToString(msg.what) + " " + logLine);
+ }
+ return logLine;
+ }
+
private void getInterfaceIndex() {
try {
mInterfaceIndex = NetworkInterface.getByName(mInterfaceName).getIndex();
} catch (SocketException | NullPointerException e) {
// TODO: throw new IllegalStateException.
- Log.e(TAG, "ALERT: Failed to get interface index: ", e);
+ Log.e(mTag, "ALERT: Failed to get interface index: ", e);
}
}
@@ -252,7 +356,7 @@
private void resetLinkProperties() {
mNetlinkTracker.clearLinkProperties();
mDhcpResults = null;
- mStaticIpConfig = null;
+ mConfiguration = null;
synchronized (mLock) {
mLinkProperties = new LinkProperties();
@@ -260,16 +364,93 @@
}
}
+ // For now: use WifiStateMachine's historical notion of provisioned.
+ private static boolean isProvisioned(LinkProperties lp) {
+ // For historical reasons, we should connect even if all we have is
+ // an IPv4 address and nothing else.
+ return lp.isProvisioned() || lp.hasIPv4Address();
+ }
+
+ // TODO: Investigate folding all this into the existing static function
+ // LinkProperties.compareProvisioning() or some other single function that
+ // takes two LinkProperties objects and returns a ProvisioningChange
+ // object that is a correct and complete assessment of what changed, taking
+ // account of the asymmetries described in the comments in this function.
+ // Then switch to using it everywhere (IpReachabilityMonitor, etc.).
+ private static ProvisioningChange compareProvisioning(
+ LinkProperties oldLp, LinkProperties newLp) {
+ ProvisioningChange delta;
+
+ final boolean wasProvisioned = isProvisioned(oldLp);
+ final boolean isProvisioned = isProvisioned(newLp);
+
+ if (!wasProvisioned && isProvisioned) {
+ delta = ProvisioningChange.GAINED_PROVISIONING;
+ } else if (wasProvisioned && isProvisioned) {
+ delta = ProvisioningChange.STILL_PROVISIONED;
+ } else if (!wasProvisioned && !isProvisioned) {
+ delta = ProvisioningChange.STILL_NOT_PROVISIONED;
+ } else {
+ // (wasProvisioned && !isProvisioned)
+ //
+ // Note that this is true even if we lose a configuration element
+ // (e.g., a default gateway) that would not be required to advance
+ // into provisioned state. This is intended: if we have a default
+ // router and we lose it, that's a sure sign of a problem, but if
+ // we connect to a network with no IPv4 DNS servers, we consider
+ // that to be a network without DNS servers and connect anyway.
+ //
+ // See the comment below.
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
+ // Additionally:
+ //
+ // Partial configurations (e.g., only an IPv4 address with no DNS
+ // servers and no default route) are accepted as long as DHCPv4
+ // succeeds. On such a network, isProvisioned() will always return
+ // false, because the configuration is not complete, but we want to
+ // connect anyway. It might be a disconnected network such as a
+ // Chromecast or a wireless printer, for example.
+ //
+ // Because on such a network isProvisioned() will always return false,
+ // delta will never be LOST_PROVISIONING. So check for loss of
+ // provisioning here too.
+ if ((oldLp.hasIPv4Address() && !newLp.hasIPv4Address()) ||
+ (oldLp.isIPv6Provisioned() && !newLp.isIPv6Provisioned())) {
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
+ return delta;
+ }
+
+ private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {
+ switch (delta) {
+ case GAINED_PROVISIONING:
+ if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }
+ mCallback.onProvisioningSuccess(newLp);
+ break;
+
+ case LOST_PROVISIONING:
+ if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
+ mCallback.onProvisioningFailure(newLp);
+ break;
+
+ default:
+ if (VDBG) { Log.d(mTag, "onLinkPropertiesChange()"); }
+ mCallback.onLinkPropertiesChange(newLp);
+ break;
+ }
+ }
+
private ProvisioningChange setLinkProperties(LinkProperties newLp) {
if (mIpReachabilityMonitor != null) {
mIpReachabilityMonitor.updateLinkProperties(newLp);
}
- // TODO: Figure out whether and how to incorporate static configuration
- // into the notion of provisioning.
ProvisioningChange delta;
synchronized (mLock) {
- delta = LinkProperties.compareProvisioning(mLinkProperties, newLp);
+ delta = compareProvisioning(mLinkProperties, newLp);
mLinkProperties = new LinkProperties(newLp);
}
@@ -277,7 +458,7 @@
switch (delta) {
case GAINED_PROVISIONING:
case LOST_PROVISIONING:
- Log.d(TAG, "provisioning: " + delta);
+ Log.d(mTag, "provisioning: " + delta);
break;
}
}
@@ -333,7 +514,7 @@
}
if (VDBG) {
- Log.d(TAG, "newLp{" + newLp + "}");
+ Log.d(mTag, "newLp{" + newLp + "}");
}
return newLp;
@@ -345,21 +526,51 @@
ifcg.setLinkAddress(new LinkAddress("0.0.0.0/0"));
mNwService.setInterfaceConfig(mInterfaceName, ifcg);
} catch (RemoteException e) {
- Log.e(TAG, "ALERT: Failed to clear IPv4 address on interface " + mInterfaceName, e);
+ Log.e(mTag, "ALERT: Failed to clear IPv4 address on interface " + mInterfaceName, e);
}
}
private void handleIPv4Success(DhcpResults dhcpResults) {
mDhcpResults = new DhcpResults(dhcpResults);
- setLinkProperties(assembleLinkProperties());
- mCallback.onIPv4ProvisioningSuccess(dhcpResults);
+ final LinkProperties newLp = assembleLinkProperties();
+ final ProvisioningChange delta = setLinkProperties(newLp);
+
+ if (VDBG) {
+ Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");
+ }
+ mCallback.onNewDhcpResults(dhcpResults);
+
+ dispatchCallback(delta, newLp);
}
private void handleIPv4Failure() {
+ // TODO: Figure out to de-dup this and the same code in DhcpClient.
clearIPv4Address();
mDhcpResults = null;
- setLinkProperties(assembleLinkProperties());
- mCallback.onIPv4ProvisioningFailure();
+ final LinkProperties newLp = assembleLinkProperties();
+ ProvisioningChange delta = setLinkProperties(newLp);
+ // If we've gotten here and we're still not provisioned treat that as
+ // a total loss of provisioning.
+ //
+ // Either (a) static IP configuration failed or (b) DHCPv4 failed AND
+ // there was no usable IPv6 obtained before the DHCPv4 timeout.
+ //
+ // Regardless: GAME OVER.
+ //
+ // TODO: Make the DHCP client not time out and just continue in
+ // exponential backoff. Callers such as Wi-Fi which need a timeout
+ // should implement it themselves.
+ if (delta == ProvisioningChange.STILL_NOT_PROVISIONED) {
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
+ if (VDBG) { Log.d(mTag, "onNewDhcpResults(null)"); }
+ mCallback.onNewDhcpResults(null);
+
+ dispatchCallback(delta, newLp);
+ if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ transitionTo(mStoppingState);
+ }
}
class StoppedState extends State {
@@ -369,7 +580,7 @@
mNwService.disableIpv6(mInterfaceName);
mNwService.clearInterfaceAddresses(mInterfaceName);
} catch (Exception e) {
- Log.e(TAG, "Failed to clear addresses or disable IPv6" + e);
+ Log.e(mTag, "Failed to clear addresses or disable IPv6" + e);
}
resetLinkProperties();
@@ -382,7 +593,7 @@
break;
case CMD_START:
- mStaticIpConfig = (StaticIpConfiguration) msg.obj;
+ mConfiguration = (ProvisioningConfiguration) msg.obj;
transitionTo(mStartedState);
break;
@@ -390,14 +601,9 @@
setLinkProperties(assembleLinkProperties());
break;
- case DhcpStateMachine.CMD_ON_QUIT:
- // CMD_ON_QUIT is really more like "EVENT_ON_QUIT".
- // Shutting down DHCPv4 progresses simultaneously with
- // transitioning to StoppedState, so we can receive this
- // message after we've already transitioned here.
- //
- // TODO: Figure out if this is actually useful and if not
- // expunge it.
+ case DhcpClient.CMD_ON_QUIT:
+ // Everything is already stopped.
+ Log.e(mTag, "Unexpected CMD_ON_QUIT (already stopped).");
break;
default:
@@ -407,6 +613,30 @@
}
}
+ class StoppingState extends State {
+ @Override
+ public void enter() {
+ if (mDhcpClient == null) {
+ // There's no DHCPv4 for which to wait; proceed to stopped.
+ transitionTo(mStoppedState);
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case DhcpClient.CMD_ON_QUIT:
+ mDhcpClient = null;
+ transitionTo(mStoppedState);
+ break;
+
+ default:
+ deferMessage(msg);
+ }
+ return HANDLED;
+ }
+ }
+
class StartedState extends State {
@Override
public void enter() {
@@ -416,48 +646,54 @@
mNwService.enableIpv6(mInterfaceName);
// TODO: Perhaps clearIPv4Address() as well.
} catch (RemoteException re) {
- Log.e(TAG, "Unable to change interface settings: " + re);
+ Log.e(mTag, "Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
- Log.e(TAG, "Unable to change interface settings: " + ie);
+ Log.e(mTag, "Unable to change interface settings: " + ie);
}
- mIpReachabilityMonitor = new IpReachabilityMonitor(
- mContext,
- mInterfaceName,
- new IpReachabilityMonitor.Callback() {
- @Override
- public void notifyLost(InetAddress ip, String logMsg) {
- if (mCallback.usingIpReachabilityMonitor()) {
+ if (mConfiguration.mUsingIpReachabilityMonitor) {
+ mIpReachabilityMonitor = new IpReachabilityMonitor(
+ mContext,
+ mInterfaceName,
+ new IpReachabilityMonitor.Callback() {
+ @Override
+ public void notifyLost(InetAddress ip, String logMsg) {
mCallback.onReachabilityLost(logMsg);
}
- }
- });
+ });
+ }
// If we have a StaticIpConfiguration attempt to apply it and
// handle the result accordingly.
- if (mStaticIpConfig != null) {
+ if (mConfiguration.mStaticIpConfig != null) {
if (applyStaticIpConfig()) {
- handleIPv4Success(new DhcpResults(mStaticIpConfig));
+ handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
- handleIPv4Failure();
+ if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
+ mCallback.onProvisioningFailure(getLinkProperties());
+ transitionTo(mStoppingState);
}
} else {
// Start DHCPv4.
- makeDhcpStateMachine();
- mDhcpStateMachine.registerForPreDhcpNotification();
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
+ mDhcpClient = DhcpClient.makeDhcpClient(
+ mContext,
+ IpManager.this,
+ mInterfaceName);
+ mDhcpClient.registerForPreDhcpNotification();
+ mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
}
}
@Override
public void exit() {
- mIpReachabilityMonitor.stop();
- mIpReachabilityMonitor = null;
+ if (mIpReachabilityMonitor != null) {
+ mIpReachabilityMonitor.stop();
+ mIpReachabilityMonitor = null;
+ }
- if (mDhcpStateMachine != null) {
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
- mDhcpStateMachine.doQuit();
- mDhcpStateMachine = null;
+ if (mDhcpClient != null) {
+ mDhcpClient.sendMessage(DhcpClient.CMD_STOP_DHCP);
+ mDhcpClient.doQuit();
}
resetLinkProperties();
@@ -471,7 +707,7 @@
break;
case CMD_START:
- Log.e(TAG, "ALERT: START received in StartedState. Please fix caller.");
+ Log.e(mTag, "ALERT: START received in StartedState. Please fix caller.");
break;
case CMD_CONFIRM:
@@ -479,7 +715,7 @@
// that both probes (a) on-link neighbors and (b) does
// a DHCPv4 RENEW. We used to do this on Wi-Fi framework
// roams.
- if (mCallback.usingIpReachabilityMonitor()) {
+ if (mIpReachabilityMonitor != null) {
mIpReachabilityMonitor.probeAll();
}
break;
@@ -488,9 +724,8 @@
// It's possible to reach here if, for example, someone
// calls completedPreDhcpAction() after provisioning with
// a static IP configuration.
- if (mDhcpStateMachine != null) {
- mDhcpStateMachine.sendMessage(
- DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE);
+ if (mDhcpClient != null) {
+ mDhcpClient.sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE);
}
break;
@@ -500,57 +735,47 @@
break;
}
final ProvisioningChange delta = setLinkProperties(newLp);
-
- // NOTE: The only receiver of these callbacks currently
- // treats all three of them identically, namely it calls
- // IpManager#getLinkProperties() and makes its own determination.
- switch (delta) {
- case GAINED_PROVISIONING:
- mCallback.onProvisioningSuccess(newLp);
- break;
-
- case LOST_PROVISIONING:
- mCallback.onProvisioningFailure(newLp);
- break;
-
- default:
- // TODO: Only notify on STILL_PROVISIONED?
- mCallback.onLinkPropertiesChange(newLp);
- break;
+ dispatchCallback(delta, newLp);
+ if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ transitionTo(mStoppedState);
}
break;
}
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
- mCallback.onPreDhcpAction();
+ case DhcpClient.CMD_PRE_DHCP_ACTION:
+ if (VDBG) { Log.d(mTag, "onPreDhcpAction()"); }
+ if (mConfiguration.mRequestedPreDhcpAction) {
+ mCallback.onPreDhcpAction();
+ } else {
+ sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE);
+ }
break;
- case DhcpStateMachine.CMD_POST_DHCP_ACTION: {
+ case DhcpClient.CMD_POST_DHCP_ACTION: {
// Note that onPostDhcpAction() is likely to be
// asynchronous, and thus there is no guarantee that we
// will be able to observe any of its effects here.
+ if (VDBG) { Log.d(mTag, "onPostDhcpAction()"); }
mCallback.onPostDhcpAction();
final DhcpResults dhcpResults = (DhcpResults) msg.obj;
switch (msg.arg1) {
- case DhcpStateMachine.DHCP_SUCCESS:
+ case DhcpClient.DHCP_SUCCESS:
handleIPv4Success(dhcpResults);
break;
- case DhcpStateMachine.DHCP_FAILURE:
+ case DhcpClient.DHCP_FAILURE:
handleIPv4Failure();
break;
default:
- Log.e(TAG, "Unknown CMD_POST_DHCP_ACTION status:" + msg.arg1);
+ Log.e(mTag, "Unknown CMD_POST_DHCP_ACTION status:" + msg.arg1);
}
break;
}
- case DhcpStateMachine.CMD_ON_QUIT:
- // CMD_ON_QUIT is really more like "EVENT_ON_QUIT".
- // Regardless, we ignore it.
- //
- // TODO: Figure out if this is actually useful and if not
- // expunge it.
+ case DhcpClient.CMD_ON_QUIT:
+ // DHCPv4 quit early for some reason.
+ Log.e(mTag, "Unexpected CMD_ON_QUIT.");
+ mDhcpClient = null;
break;
default:
@@ -561,35 +786,17 @@
private boolean applyStaticIpConfig() {
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
- ifcg.setLinkAddress(mStaticIpConfig.ipAddress);
+ ifcg.setLinkAddress(mConfiguration.mStaticIpConfig.ipAddress);
ifcg.setInterfaceUp();
try {
mNwService.setInterfaceConfig(mInterfaceName, ifcg);
- if (DBG) Log.d(TAG, "Static IP configuration succeeded");
+ if (DBG) Log.d(mTag, "Static IP configuration succeeded");
} catch (IllegalStateException | RemoteException e) {
- Log.e(TAG, "Static IP configuration failed: ", e);
+ Log.e(mTag, "Static IP configuration failed: ", e);
return false;
}
return true;
}
-
- private void makeDhcpStateMachine() {
- final boolean usingLegacyDhcp = (Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.LEGACY_DHCP_CLIENT, 0) == 1);
-
- if (usingLegacyDhcp) {
- mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
- mContext,
- IpManager.this,
- mInterfaceName);
- } else {
- mDhcpStateMachine = DhcpClient.makeDhcpStateMachine(
- mContext,
- IpManager.this,
- mInterfaceName);
- }
- }
}
}
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 23a69d1..69259d0 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -17,6 +17,7 @@
package com.android.ims.internal;
import com.android.ims.ImsReasonInfo;
+
/**
* A listener type for receiving notifications about the changes to
* the IMS connection(registration).
@@ -26,15 +27,36 @@
interface IImsRegistrationListener {
/**
* Notifies the application when the device is connected to the IMS network.
+ *
+ * @deprecated see {@link registrationConnectedWithRadioTech}
*/
void registrationConnected();
/**
* Notifies the application when the device is trying to connect the IMS network.
+ *
+ * @deprecated see {@link registrationProgressingWithRadioTech}
*/
void registrationProgressing();
/**
+ * Notifies the application when the device is connected to the IMS network.
+ *
+ * @param imsRadioTech the radio access technology. Valid values are {@code
+ * RIL_RADIO_TECHNOLOGY_*} defined in {@link ServiceState}.
+ */
+ void registrationConnectedWithRadioTech(int imsRadioTech);
+
+ /**
+ * Notifies the application when the device is trying to connect the IMS network.
+ *
+ * @param imsRadioTech the radio access technology. Valid values are {@code
+ * RIL_RADIO_TECHNOLOGY_*} defined in {@link ServiceState}.
+ */
+ void registrationProgressingWithRadioTech(int imsRadioTech);
+
+
+ /**
* Notifies the application when the device is disconnected from the IMS network.
*/
void registrationDisconnected(in ImsReasonInfo imsReasonInfo);
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 429839f..bba357e 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -92,7 +92,33 @@
int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */
int NETWORK_ERR = 49; /* Received error from network */
int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent requests */
-
+ // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to
+ // reveal particular replacement for Generic failure
+ int OEM_ERROR_1 = 501;
+ int OEM_ERROR_2 = 502;
+ int OEM_ERROR_3 = 503;
+ int OEM_ERROR_4 = 504;
+ int OEM_ERROR_5 = 505;
+ int OEM_ERROR_6 = 506;
+ int OEM_ERROR_7 = 507;
+ int OEM_ERROR_8 = 508;
+ int OEM_ERROR_9 = 509;
+ int OEM_ERROR_10 = 510;
+ int OEM_ERROR_11 = 511;
+ int OEM_ERROR_12 = 512;
+ int OEM_ERROR_13 = 513;
+ int OEM_ERROR_14 = 514;
+ int OEM_ERROR_15 = 515;
+ int OEM_ERROR_16 = 516;
+ int OEM_ERROR_17 = 517;
+ int OEM_ERROR_18 = 518;
+ int OEM_ERROR_19 = 519;
+ int OEM_ERROR_20 = 520;
+ int OEM_ERROR_21 = 521;
+ int OEM_ERROR_22 = 522;
+ int OEM_ERROR_23 = 523;
+ int OEM_ERROR_24 = 524;
+ int OEM_ERROR_25 = 525;
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
@@ -124,6 +150,26 @@
int PREFERRED_NETWORK_MODE = SystemProperties.getInt("ro.telephony.default_network",
NETWORK_MODE_WCDMA_PREF);
+ int BAND_MODE_UNSPECIFIED = 0; //"unspecified" (selected by baseband automatically)
+ int BAND_MODE_EURO = 1; //"EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
+ int BAND_MODE_USA = 2; //"US band" (GSM-850 / PCS-1900 / WCDMA-850 / WCDMA-PCS-1900)
+ int BAND_MODE_JPN = 3; //"JPN band" (WCDMA-800 / WCDMA-IMT-2000)
+ int BAND_MODE_AUS = 4; //"AUS band" (GSM-900 / DCS-1800 / WCDMA-850 / WCDMA-IMT-2000)
+ int BAND_MODE_AUS_2 = 5; //"AUS band 2" (GSM-900 / DCS-1800 / WCDMA-850)
+ int BAND_MODE_CELL_800 = 6; //"Cellular" (800-MHz Band)
+ int BAND_MODE_PCS = 7; //"PCS" (1900-MHz Band)
+ int BAND_MODE_JTACS = 8; //"Band Class 3" (JTACS Band)
+ int BAND_MODE_KOREA_PCS = 9; //"Band Class 4" (Korean PCS Band)
+ int BAND_MODE_5_450M = 10; //"Band Class 5" (450-MHz Band)
+ int BAND_MODE_IMT2000 = 11; //"Band Class 6" (2-GMHz IMT2000 Band)
+ int BAND_MODE_7_700M_2 = 12; //"Band Class 7" (Upper 700-MHz Band)
+ int BAND_MODE_8_1800M = 13; //"Band Class 8" (1800-MHz Band)
+ int BAND_MODE_9_900M = 14; //"Band Class 9" (900-MHz Band)
+ int BAND_MODE_10_800M_2 = 15; //"Band Class 10" (Secondary 800-MHz Band)
+ int BAND_MODE_EURO_PAMR_400M = 16; //"Band Class 11" (400-MHz European PAMR Band)
+ int BAND_MODE_AWS = 17; //"Band Class 15" (AWS Band)
+ int BAND_MODE_USA_2500M = 18; //"Band Class 16" (US 2.5-GHz Band)
+
int CDMA_CELL_BROADCAST_SMS_DISABLED = 1;
int CDMA_CELL_BROADCAST_SMS_ENABLED = 0;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 5d94e53..a6aad3c 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -238,12 +238,24 @@
public String BSSID;
/**
+ * 2GHz band.
+ * @hide
+ */
+ public static final int AP_BAND_2GHZ = 0;
+
+ /**
+ * 5GHz band.
+ * @hide
+ */
+ public static final int AP_BAND_5GHZ = 1;
+
+ /**
* The band which AP resides on
* 0-2G 1-5G
* By default, 2G is chosen
* @hide
*/
- public int apBand = 0;
+ public int apBand = AP_BAND_2GHZ;
/**
* The channel which AP resides on,currently, US only
@@ -1755,11 +1767,6 @@
}
/** @hide */
- public boolean isVisibleToUser(int userId) {
- return shared || (UserHandle.getUserId(creatorUid) == userId);
- }
-
- /** @hide */
public void setPasspointManagementObjectTree(String passpointManagementObjectTree) {
mPasspointManagementObjectTree = passpointManagementObjectTree;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4133cda..55b9182 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -44,6 +44,7 @@
import com.android.internal.util.Protocol;
import java.net.InetAddress;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -884,6 +885,24 @@
}
/**
+ * Sets whether or not the given network is metered from a network policy
+ * point of view. A network should be classified as metered when the user is
+ * sensitive to heavy data usage on that connection due to monetary costs,
+ * data limitations or battery/performance issues. A typical example would
+ * be a wifi connection where the user was being charged for usage.
+ * @param netId the integer that identifies the network configuration
+ * to the supplicant.
+ * @param isMetered True to mark the network as metered.
+ * @return {@code true} if the operation succeeded.
+ * @hide
+ */
+ @SystemApi
+ public boolean setMetered(int netId, boolean isMetered) {
+ // TODO(jjoslin): Implement
+ return false;
+ }
+
+ /**
* Remove the specified network from the list of configured networks.
* This may result in the asynchronous delivery of state change
* events.
@@ -1293,13 +1312,15 @@
* @return the list of access points found in the most recent scan. An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
- * in order to get valid results.
+ * in order to get valid results. If there is a remote exception (e.g., either a communication
+ * problem with the system service or an exception within the framework) an empty list will be
+ * returned.
*/
public List<ScanResult> getScanResults() {
try {
return mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
- return null;
+ return new ArrayList<ScanResult>();
}
}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanEventListener.java b/wifi/java/android/net/wifi/nan/WifiNanEventListener.java
index 5c18bd7..9e6ed4e 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanEventListener.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanEventListener.java
@@ -36,7 +36,7 @@
*/
public class WifiNanEventListener {
private static final String TAG = "WifiNanEventListener";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
/**
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index cb82268..667c4b1 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -38,7 +38,7 @@
*/
public class WifiNanManager {
private static final String TAG = "WifiNanManager";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
private IBinder mBinder;
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java
index d0a9410..bc1787f 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java
@@ -27,7 +27,7 @@
*/
public class WifiNanSession {
private static final String TAG = "WifiNanSession";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
/**
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
index 0925087..b9af7def 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
@@ -43,7 +43,7 @@
*/
public class WifiNanSessionListener {
private static final String TAG = "WifiNanSessionListener";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
/**