diff options
author | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-11-05 02:27:28 +0000 |
---|---|---|
committer | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-11-05 15:13:26 +0000 |
commit | a89168479cb14f482268af6f1a650b28eba0b393 (patch) | |
tree | 8552b9d49ecfad6a453ee5f743571b700b4d3d3c /core/java/android/net | |
parent | 8331d3e508498a19c296fed41b9d4b23ea960031 (diff) | |
parent | 25b5096f154721c8142d54f1b3af9e2998deffe9 (diff) | |
download | frameworks_base-a89168479cb14f482268af6f1a650b28eba0b393.zip frameworks_base-a89168479cb14f482268af6f1a650b28eba0b393.tar.gz frameworks_base-a89168479cb14f482268af6f1a650b28eba0b393.tar.bz2 |
Merge tag 'android-6.0.0_r26' into HEAD
Android 6.0.0 release 26
Conflicts:
cmds/bootanimation/BootAnimation.cpp
core/java/android/accounts/AccountManager.java
core/java/android/app/AppOpsManager.java
core/java/android/os/PowerManagerInternal.java
core/java/android/os/storage/IMountService.java
core/java/android/provider/Settings.java
core/java/com/android/internal/widget/ILockSettings.aidl
core/res/res/values-mcc204-mnc12/config.xml
core/res/res/values-mcc219-mnc02/config.xml
core/res/res/values-mcc730-mnc07/config.xml
core/res/res/values/config.xml
core/res/res/values/symbols.xml
packages/SystemUI/res/values/config.xml
packages/SystemUI/src/com/android/systemui/doze/DozeService.java
packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
services/core/java/com/android/server/LocationManagerService.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/power/PowerManagerService.java
telecomm/java/android/telecom/Phone.java
telephony/java/android/telephony/CarrierConfigManager.java
telephony/java/android/telephony/RadioAccessFamily.java
telephony/java/android/telephony/ServiceState.java
telephony/java/android/telephony/SignalStrength.java
telephony/java/android/telephony/TelephonyManager.java
telephony/java/com/android/ims/ImsCallProfile.java
telephony/java/com/android/ims/ImsReasonInfo.java
telephony/java/com/android/ims/ImsSuppServiceNotification.aidl
telephony/java/com/android/ims/ImsSuppServiceNotification.java
telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
telephony/java/com/android/internal/telephony/RILConstants.java
Change-Id: I99c6edb8e25a77145b5adef97d0d55bfbe676959
Diffstat (limited to 'core/java/android/net')
-rw-r--r-- | core/java/android/net/ConnectivityManager.java | 161 | ||||
-rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 5 | ||||
-rw-r--r-- | core/java/android/net/IpReachabilityMonitor.java | 35 | ||||
-rw-r--r-- | core/java/android/net/NetworkAgent.java | 120 | ||||
-rw-r--r-- | core/java/android/net/NetworkCapabilities.java | 185 | ||||
-rw-r--r-- | core/java/android/net/NetworkFactory.java | 6 | ||||
-rw-r--r-- | core/java/android/net/NetworkRequest.java | 18 |
7 files changed, 505 insertions, 25 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 15016c2..11e0b48 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -102,6 +102,16 @@ public class ConnectivityManager { public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; /** + * A temporary hack until SUPL system can get off the legacy APIS. + * They do too many network requests and the long list of apps listening + * and waking due to the CONNECTIVITY_ACTION bcast makes it expensive. + * Use this bcast intent instead for SUPL requests. + * @hide + */ + public static final String CONNECTIVITY_ACTION_SUPL = + "android.net.conn.CONNECTIVITY_CHANGE_SUPL"; + + /** * The device has connected to a network that has presented a captive * portal, which is blocking Internet connectivity. The user was presented * with a notification that network sign in is required, @@ -1049,11 +1059,13 @@ public class ConnectivityManager { type = "enableDUN"; result = TYPE_MOBILE_DUN; } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { - type = "enableSUPL"; + type = "enableSUPL"; result = TYPE_MOBILE_SUPL; - } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { - type = "enableMMS"; - result = TYPE_MOBILE_MMS; + // back out this hack for mms as they no longer need this and it's causing + // device slowdowns - b/23350688 (note, supl still needs this) + //} else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { + // type = "enableMMS"; + // result = TYPE_MOBILE_MMS; } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { type = "enableHIPRI"; result = TYPE_MOBILE_HIPRI; @@ -1190,6 +1202,144 @@ public class ConnectivityManager { return true; } + /** @hide */ + public static class PacketKeepaliveCallback { + /** The requested keepalive was successfully started. */ + public void onStarted() {} + /** The keepalive was successfully stopped. */ + public void onStopped() {} + /** An error occurred. */ + public void onError(int error) {} + } + + /** + * Allows applications to request that the system periodically send specific packets on their + * behalf, using hardware offload to save battery power. + * + * To request that the system send keepalives, call one of the methods that return a + * {@link ConnectivityManager.PacketKeepalive} object, such as {@link #startNattKeepalive}, + * passing in a non-null callback. If the callback is successfully started, the callback's + * {@code onStarted} method will be called. If an error occurs, {@code onError} will be called, + * specifying one of the {@code ERROR_*} constants in this class. + * + * To stop an existing keepalive, call {@link stop}. The system will call {@code onStopped} if + * the operation was successfull or {@code onError} if an error occurred. + * + * @hide + */ + public class PacketKeepalive { + + private static final String TAG = "PacketKeepalive"; + + /** @hide */ + public static final int SUCCESS = 0; + + /** @hide */ + public static final int NO_KEEPALIVE = -1; + + /** @hide */ + public static final int BINDER_DIED = -10; + + /** The specified {@code Network} is not connected. */ + public static final int ERROR_INVALID_NETWORK = -20; + /** The specified IP addresses are invalid. For example, the specified source IP address is + * not configured on the specified {@code Network}. */ + public static final int ERROR_INVALID_IP_ADDRESS = -21; + /** The requested port is invalid. */ + public static final int ERROR_INVALID_PORT = -22; + /** The packet length is invalid (e.g., too long). */ + public static final int ERROR_INVALID_LENGTH = -23; + /** The packet transmission interval is invalid (e.g., too short). */ + public static final int ERROR_INVALID_INTERVAL = -24; + + /** The hardware does not support this request. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = -30; + /** The hardware returned an error. */ + public static final int ERROR_HARDWARE_ERROR = -31; + + public static final int NATT_PORT = 4500; + + private final Network mNetwork; + private final PacketKeepaliveCallback mCallback; + private final Looper mLooper; + private final Messenger mMessenger; + + private volatile Integer mSlot; + + void stopLooper() { + mLooper.quit(); + } + + public void stop() { + try { + mService.stopKeepalive(mNetwork, mSlot); + } catch (RemoteException e) { + Log.e(TAG, "Error stopping packet keepalive: ", e); + stopLooper(); + } + } + + private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { + checkNotNull(network, "network cannot be null"); + checkNotNull(callback, "callback cannot be null"); + mNetwork = network; + mCallback = callback; + HandlerThread thread = new HandlerThread(TAG); + thread.start(); + mLooper = thread.getLooper(); + mMessenger = new Messenger(new Handler(mLooper) { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case NetworkAgent.EVENT_PACKET_KEEPALIVE: + int error = message.arg2; + try { + if (error == SUCCESS) { + if (mSlot == null) { + mSlot = message.arg1; + mCallback.onStarted(); + } else { + mSlot = null; + stopLooper(); + mCallback.onStopped(); + } + } else { + stopLooper(); + mCallback.onError(error); + } + } catch (Exception e) { + Log.e(TAG, "Exception in keepalive callback(" + error + ")", e); + } + break; + default: + Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what)); + break; + } + } + }); + } + } + + /** + * Starts an IPsec NAT-T keepalive packet with the specified parameters. + * + * @hide + */ + public PacketKeepalive startNattKeepalive( + Network network, int intervalSeconds, PacketKeepaliveCallback callback, + InetAddress srcAddr, int srcPort, InetAddress dstAddr) { + final PacketKeepalive k = new PacketKeepalive(network, callback); + try { + mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(), + srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress()); + } catch (RemoteException e) { + Log.e(TAG, "Error starting packet keepalive: ", e); + k.stopLooper(); + return null; + } + return k; + } + /** * Ensure that a network route exists to deliver traffic to the specified * host via the specified network interface. An attempt to add a route that @@ -2136,6 +2286,7 @@ public class ConnectivityManager { private final AtomicInteger mRefCount; private static final String TAG = "ConnectivityManager.CallbackHandler"; private final ConnectivityManager mCm; + private static final boolean DBG = false; CallbackHandler(Looper looper, HashMap<NetworkRequest, NetworkCallback>callbackMap, AtomicInteger refCount, ConnectivityManager cm) { @@ -2147,7 +2298,7 @@ public class ConnectivityManager { @Override public void handleMessage(Message message) { - Log.d(TAG, "CM callback handler got msg " + message.what); + if (DBG) Log.d(TAG, "CM callback handler got msg " + message.what); NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class); Network network = (Network) getObject(message, Network.class); switch (message.what) { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 523dfe1..c6de7a5 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -165,4 +165,9 @@ interface IConnectivityManager boolean setUnderlyingNetworksForVpn(in Network[] networks); void factoryReset(); + + void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger, + in IBinder binder, String srcAddr, int srcPort, String dstAddr); + + void stopKeepalive(in Network network, int slot); } diff --git a/core/java/android/net/IpReachabilityMonitor.java b/core/java/android/net/IpReachabilityMonitor.java index 88fb014..2283004 100644 --- a/core/java/android/net/IpReachabilityMonitor.java +++ b/core/java/android/net/IpReachabilityMonitor.java @@ -18,6 +18,7 @@ package android.net; import com.android.internal.annotations.GuardedBy; +import android.content.Context; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LinkProperties.ProvisioningChange; @@ -31,6 +32,7 @@ import android.net.netlink.RtNetlinkNeighborMessage; import android.net.netlink.StructNdaCacheInfo; import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlMsgHdr; +import android.os.PowerManager; import android.os.SystemClock; import android.system.ErrnoException; import android.system.NetlinkSocketAddress; @@ -74,6 +76,7 @@ public class IpReachabilityMonitor { } private final Object mLock = new Object(); + private final PowerManager.WakeLock mWakeLock; private final String mInterfaceName; private final int mInterfaceIndex; private final Callback mCallback; @@ -136,7 +139,8 @@ public class IpReachabilityMonitor { return returnValue; } - public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException { + public IpReachabilityMonitor(Context context, String ifName, Callback callback) + throws IllegalArgumentException { mInterfaceName = ifName; int ifIndex = -1; try { @@ -145,6 +149,8 @@ public class IpReachabilityMonitor { } catch (SocketException | NullPointerException e) { throw new IllegalArgumentException("invalid interface '" + ifName + "': ", e); } + mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, TAG + "." + mInterfaceName); mCallback = callback; mNetlinkSocketObserver = new NetlinkSocketObserver(); mObserverThread = new Thread(mNetlinkSocketObserver); @@ -291,6 +297,17 @@ public class IpReachabilityMonitor { synchronized (mLock) { ipProbeList.addAll(mIpWatchList.keySet()); } + + if (!ipProbeList.isEmpty() && stillRunning()) { + // Keep the CPU awake long enough to allow all ARP/ND + // probes a reasonable chance at success. See b/23197666. + // + // The wakelock we use is (by default) refcounted, and this version + // of acquire(timeout) queues a release message to keep acquisitions + // and releases balanced. + mWakeLock.acquire(getProbeWakeLockDuration()); + } + for (InetAddress target : ipProbeList) { if (!stillRunning()) { break; @@ -299,6 +316,22 @@ public class IpReachabilityMonitor { } } + private long getProbeWakeLockDuration() { + // Ideally, this would be computed by examining the values of: + // + // /proc/sys/net/ipv[46]/neigh/<ifname>/ucast_solicit + // + // and: + // + // /proc/sys/net/ipv[46]/neigh/<ifname>/retrans_time_ms + // + // For now, just make some assumptions. + final long numUnicastProbes = 3; + final long retransTimeMs = 1000; + final long gracePeriodMs = 500; + return (numUnicastProbes * retransTimeMs) + gracePeriodMs; + } + // TODO: simply the number of objects by making this extend Thread. private final class NetlinkSocketObserver implements Runnable { diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 808a882..20c2168 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -17,6 +17,7 @@ package android.net; import android.content.Context; +import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -25,6 +26,7 @@ import android.util.Log; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import android.net.ConnectivityManager.PacketKeepalive; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; @@ -143,17 +145,60 @@ public abstract class NetworkAgent extends Handler { */ public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9; - /** Sent by ConnectivityService to the NetworkAgent to inform the agent to pull + /** + * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull * the underlying network connection for updated bandwidth information. */ public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10; /** + * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent + * periodically on the given interval. + * + * arg1 = the slot number of the keepalive to start + * arg2 = interval in seconds + * obj = KeepalivePacketData object describing the data to be sent + * + * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + */ + public static final int CMD_START_PACKET_KEEPALIVE = BASE + 11; + + /** + * Requests that the specified keepalive packet be stopped. + * + * arg1 = slot number of the keepalive to stop. + * + * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + */ + public static final int CMD_STOP_PACKET_KEEPALIVE = BASE + 12; + + /** + * Sent by the NetworkAgent to ConnectivityService to provide status on a packet keepalive + * request. This may either be the reply to a CMD_START_PACKET_KEEPALIVE, or an asynchronous + * error notification. + * + * This is also sent by KeepaliveTracker to the app's ConnectivityManager.PacketKeepalive to + * so that the app's PacketKeepaliveCallback methods can be called. + * + * arg1 = slot number of the keepalive + * arg2 = error code + */ + public static final int EVENT_PACKET_KEEPALIVE = BASE + 13; + + /** + * Sent by ConnectivityService to inform this network transport of signal strength thresholds + * that when crossed should trigger a system wakeup and a NetworkCapabilities update. + * + * obj = int[] describing signal strength thresholds. + */ + public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14; + + /** * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid * automatically reconnecting to this network (e.g. via autojoin). Happens * when user selects "No" option on the "Stay connected?" dialog box. */ - public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 11; + public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15; public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { @@ -249,6 +294,27 @@ public abstract class NetworkAgent extends Handler { saveAcceptUnvalidated(msg.arg1 != 0); break; } + case CMD_START_PACKET_KEEPALIVE: { + startPacketKeepalive(msg); + break; + } + case CMD_STOP_PACKET_KEEPALIVE: { + stopPacketKeepalive(msg); + break; + } + + case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: { + ArrayList<Integer> thresholds = + ((Bundle) msg.obj).getIntegerArrayList("thresholds"); + // TODO: Change signal strength thresholds API to use an ArrayList<Integer> + // rather than convert to int[]. + int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0]; + for (int i = 0; i < intThresholds.length; i++) { + intThresholds[i] = thresholds.get(i); + } + setSignalStrengthThresholds(intThresholds); + break; + } case CMD_PREVENT_AUTOMATIC_RECONNECT: { preventAutomaticReconnect(); break; @@ -257,13 +323,27 @@ public abstract class NetworkAgent extends Handler { } private void queueOrSendMessage(int what, Object obj) { + queueOrSendMessage(what, 0, 0, obj); + } + + private void queueOrSendMessage(int what, int arg1, int arg2) { + queueOrSendMessage(what, arg1, arg2, null); + } + + private void queueOrSendMessage(int what, int arg1, int arg2, Object obj) { + Message msg = Message.obtain(); + msg.what = what; + msg.arg1 = arg1; + msg.arg2 = arg2; + msg.obj = obj; + queueOrSendMessage(msg); + } + + private void queueOrSendMessage(Message msg) { synchronized (mPreConnectedQueue) { if (mAsyncChannel != null) { - mAsyncChannel.sendMessage(what, obj); + mAsyncChannel.sendMessage(msg); } else { - Message msg = Message.obtain(); - msg.what = what; - msg.obj = obj; mPreConnectedQueue.add(msg); } } @@ -378,6 +458,34 @@ public abstract class NetworkAgent extends Handler { } /** + * Requests that the network hardware send the specified packet at the specified interval. + */ + protected void startPacketKeepalive(Message msg) { + onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + } + + /** + * Requests that the network hardware send the specified packet at the specified interval. + */ + protected void stopPacketKeepalive(Message msg) { + onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + } + + /** + * Called by the network when a packet keepalive event occurs. + */ + public void onPacketKeepaliveEvent(int slot, int reason) { + queueOrSendMessage(EVENT_PACKET_KEEPALIVE, slot, reason); + } + + /** + * Called by ConnectivityService to inform this network transport of signal strength thresholds + * that when crossed should trigger a system wakeup and a NetworkCapabilities update. + */ + protected void setSignalStrengthThresholds(int[] thresholds) { + } + + /** * Called when the user asks to not stay connected to this network because it was found to not * provide Internet access. Usually followed by call to {@code unwanted}. The transport is * responsible for making sure the device does not automatically reconnect to the same network diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index d0e0cbe..3bd12c0 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -48,6 +48,7 @@ public final class NetworkCapabilities implements Parcelable { mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; + mSignalStrength = nc.mSignalStrength; } } @@ -60,6 +61,7 @@ public final class NetworkCapabilities implements Parcelable { mNetworkCapabilities = mTransportTypes = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0; mNetworkSpecifier = null; + mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; } /** @@ -184,6 +186,28 @@ public final class NetworkCapabilities implements Parcelable { private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL; /** + * Network capabilities that are expected to be mutable, i.e., can change while a particular + * network is connected. + */ + private static final long MUTABLE_CAPABILITIES = + // TRUSTED can change when user explicitly connects to an untrusted network in Settings. + // http://b/18206275 + (1 << NET_CAPABILITY_TRUSTED) | + (1 << NET_CAPABILITY_VALIDATED) | + (1 << NET_CAPABILITY_CAPTIVE_PORTAL); + + /** + * Network capabilities that are not allowed in NetworkRequests. This exists because the + * NetworkFactory / NetworkAgent model does not deal well with the situation where a + * capability's presence cannot be known in advance. If such a capability is requested, then we + * can get into a cycle where the NetworkFactory endlessly churns out NetworkAgents that then + * get immediately torn down because they do not have the requested capability. + */ + private static final long NON_REQUESTABLE_CAPABILITIES = + (1 << NET_CAPABILITY_VALIDATED) | + (1 << NET_CAPABILITY_CAPTIVE_PORTAL); + + /** * Capabilities that are set by default when the object is constructed. */ private static final long DEFAULT_CAPABILITIES = @@ -278,8 +302,31 @@ public final class NetworkCapabilities implements Parcelable { this.mNetworkCapabilities |= nc.mNetworkCapabilities; } - private boolean satisfiedByNetCapabilities(NetworkCapabilities nc) { - return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities); + /** + * Convenience function that returns a human-readable description of the first mutable + * capability we find. Used to present an error message to apps that request mutable + * capabilities. + * + * @hide + */ + public String describeFirstNonRequestableCapability() { + if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED"; + if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL"; + // This cannot happen unless the preceding checks are incomplete. + if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) { + return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities); + } + if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth"; + if (hasSignalStrength()) return "signalStrength"; + return null; + } + + private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { + long networkCapabilities = this.mNetworkCapabilities; + if (onlyImmutable) { + networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES; + } + return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities); } /** @hide */ @@ -287,6 +334,11 @@ public final class NetworkCapabilities implements Parcelable { return (nc.mNetworkCapabilities == this.mNetworkCapabilities); } + private boolean equalsNetCapabilitiesImmutable(NetworkCapabilities that) { + return ((this.mNetworkCapabilities & ~MUTABLE_CAPABILITIES) == + (that.mNetworkCapabilities & ~MUTABLE_CAPABILITIES)); + } + /** * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are * typically provided by restricted networks. @@ -555,26 +607,130 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Magic value that indicates no signal strength provided. A request specifying this value is + * always satisfied. + * + * @hide + */ + public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE; + + /** + * Signal strength. This is a signed integer, and higher values indicate better signal. + * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI. + */ + private int mSignalStrength; + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a stronger + * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units + * reported by WifiManager. + * <p> + * Note that when used to register a network callback, this specifies the minimum acceptable + * signal strength. When received as the state of an existing network it specifies the current + * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no + * effect when requesting a callback. + * + * @param signalStrength the bearer-specific signal strength. + * @hide + */ + public void setSignalStrength(int signalStrength) { + mSignalStrength = signalStrength; + } + + /** + * Returns {@code true} if this object specifies a signal strength. + * + * @hide + */ + public boolean hasSignalStrength() { + return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED; + } + + /** + * Retrieves the signal strength. + * + * @return The bearer-specific signal strength. + * @hide + */ + public int getSignalStrength() { + return mSignalStrength; + } + + private void combineSignalStrength(NetworkCapabilities nc) { + this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength); + } + + private boolean satisfiedBySignalStrength(NetworkCapabilities nc) { + return this.mSignalStrength <= nc.mSignalStrength; + } + + private boolean equalsSignalStrength(NetworkCapabilities nc) { + return this.mSignalStrength == nc.mSignalStrength; + } + + /** * Combine a set of Capabilities to this one. Useful for coming up with the complete set - * {@hide} + * @hide */ public void combineCapabilities(NetworkCapabilities nc) { combineNetCapabilities(nc); combineTransportTypes(nc); combineLinkBandwidths(nc); combineSpecifiers(nc); + combineSignalStrength(nc); } /** - * Check if our requirements are satisfied by the given Capabilities. - * {@hide} + * Check if our requirements are satisfied by the given {@code NetworkCapabilities}. + * + * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. + * @param onlyImmutable if {@code true}, do not consider mutable requirements such as link + * bandwidth, signal strength, or validation / captive portal status. + * + * @hide */ - public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) { + private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { return (nc != null && - satisfiedByNetCapabilities(nc) && + satisfiedByNetCapabilities(nc, onlyImmutable) && satisfiedByTransportTypes(nc) && - satisfiedByLinkBandwidths(nc) && - satisfiedBySpecifier(nc)); + (onlyImmutable || satisfiedByLinkBandwidths(nc)) && + satisfiedBySpecifier(nc) && + (onlyImmutable || satisfiedBySignalStrength(nc))); + } + + /** + * Check if our requirements are satisfied by the given {@code NetworkCapabilities}. + * + * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. + * + * @hide + */ + public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) { + return satisfiedByNetworkCapabilities(nc, false); + } + + /** + * Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}. + * + * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. + * + * @hide + */ + public boolean satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc) { + return satisfiedByNetworkCapabilities(nc, true); + } + + /** + * Checks that our immutable capabilities are the same as those of the given + * {@code NetworkCapabilities}. + * + * @hide + */ + public boolean equalImmutableCapabilities(NetworkCapabilities nc) { + if (nc == null) return false; + return (equalsNetCapabilitiesImmutable(nc) && + equalsTransportTypes(nc) && + equalsSpecifier(nc)); } @Override @@ -584,6 +740,7 @@ public final class NetworkCapabilities implements Parcelable { return (equalsNetCapabilities(that) && equalsTransportTypes(that) && equalsLinkBandwidths(that) && + equalsSignalStrength(that) && equalsSpecifier(that)); } @@ -595,7 +752,8 @@ public final class NetworkCapabilities implements Parcelable { ((int)(mTransportTypes >> 32) * 7) + (mLinkUpBandwidthKbps * 11) + (mLinkDownBandwidthKbps * 13) + - (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17)); + (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17) + + (mSignalStrength * 19)); } @Override @@ -609,7 +767,9 @@ public final class NetworkCapabilities implements Parcelable { dest.writeInt(mLinkUpBandwidthKbps); dest.writeInt(mLinkDownBandwidthKbps); dest.writeString(mNetworkSpecifier); + dest.writeInt(mSignalStrength); } + public static final Creator<NetworkCapabilities> CREATOR = new Creator<NetworkCapabilities>() { @Override @@ -621,6 +781,7 @@ public final class NetworkCapabilities implements Parcelable { netCap.mLinkUpBandwidthKbps = in.readInt(); netCap.mLinkDownBandwidthKbps = in.readInt(); netCap.mNetworkSpecifier = in.readString(); + netCap.mSignalStrength = in.readInt(); return netCap; } @Override @@ -678,6 +839,8 @@ public final class NetworkCapabilities implements Parcelable { String specifier = (mNetworkSpecifier == null ? "" : " Specifier: <" + mNetworkSpecifier + ">"); - return "[" + transports + capabilities + upBand + dnBand + specifier + "]"; + String signalStrength = (hasSignalStrength() ? " SignalStrength: " + mSignalStrength : ""); + + return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]"; } } diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java index 5f46c73..cab88b9 100644 --- a/core/java/android/net/NetworkFactory.java +++ b/core/java/android/net/NetworkFactory.java @@ -169,7 +169,8 @@ public class NetworkFactory extends Handler { } } - private void handleAddRequest(NetworkRequest request, int score) { + @VisibleForTesting + protected void handleAddRequest(NetworkRequest request, int score) { NetworkRequestInfo n = mNetworkRequests.get(request.requestId); if (n == null) { if (DBG) log("got request " + request + " with score " + score); @@ -184,7 +185,8 @@ public class NetworkFactory extends Handler { evalRequest(n); } - private void handleRemoveRequest(NetworkRequest request) { + @VisibleForTesting + protected void handleRemoveRequest(NetworkRequest request) { NetworkRequestInfo n = mNetworkRequests.get(request.requestId); if (n != null) { mNetworkRequests.remove(request.requestId); diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index e184ec4..7da4818 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -191,6 +191,24 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); return this; } + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a + * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same + * RSSI units reported by WifiManager. + * <p> + * Note that when used to register a network callback, this specifies the minimum acceptable + * signal strength. When received as the state of an existing network it specifies the + * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when + * received and has no effect when requesting a callback. + * + * @param signalStrength the bearer-specific signal strength. + * @hide + */ + public Builder setSignalStrength(int signalStrength) { + mNetworkCapabilities.setSignalStrength(signalStrength); + return this; + } } // implement the Parcelable interface |