Merge "Add ability to dump events in a timeline view."
diff --git a/Android.mk b/Android.mk
index 2571afb..435d571 100644
--- a/Android.mk
+++ b/Android.mk
@@ -772,7 +772,6 @@
include libcore/Docs.mk
non_base_dirs := \
- ../opt/telephony/src/java/android/provider \
../opt/telephony/src/java/android/telephony \
../opt/telephony/src/java/android/telephony/gsm \
../opt/net/voip/src/java/android/net/rtp \
diff --git a/api/current.txt b/api/current.txt
index 55dda04..4275e9d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23784,8 +23784,8 @@
method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
method public deprecated void setNetworkPreference(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 5e9c7e3..f33d506 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25572,8 +25572,8 @@
method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
method public deprecated void setNetworkPreference(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 5487a97..bd96efb 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -23858,8 +23858,8 @@
method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int);
+ method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
method public deprecated void setNetworkPreference(int);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 234bef7..9e8acd0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -17,6 +17,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -1465,9 +1466,7 @@
// Map from type to transports.
final int NOT_FOUND = -1;
final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND);
- if (transport == NOT_FOUND) {
- throw new IllegalArgumentException("unknown legacy type: " + type);
- }
+ Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type);
nc.addTransportType(transport);
// Map from type to capabilities.
@@ -1813,9 +1812,7 @@
*/
public void removeDefaultNetworkActiveListener(OnNetworkActiveListener l) {
INetworkActivityListener rl = mNetworkActivityListeners.get(l);
- if (rl == null) {
- throw new IllegalArgumentException("Listener not registered: " + l);
- }
+ Preconditions.checkArgument(rl != null, "Listener was not registered.");
try {
getNetworkManagementService().unregisterNetworkActivityListener(rl);
} catch (RemoteException e) {
@@ -1872,9 +1869,8 @@
/** {@hide} */
public static final void enforceTetherChangePermission(Context context, String callingPkg) {
- if (null == context || null == callingPkg) {
- throw new IllegalArgumentException("arguments should not be null");
- }
+ Preconditions.checkNotNull(context, "Context cannot be null");
+ Preconditions.checkNotNull(callingPkg, "callingPkg cannot be null");
if (context.getResources().getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app).length == 2) {
@@ -2647,7 +2643,7 @@
/**
* Called if no network is found in the timeout time specified in
- * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)} call. This callback is not
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call. This callback is not
* called for the version of {@link #requestNetwork(NetworkRequest, NetworkCallback)}
* without timeout. When this callback is invoked the associated
* {@link NetworkRequest} will have already been removed and released, as if
@@ -2772,84 +2768,67 @@
}
CallbackHandler(Handler handler) {
- this(handler.getLooper());
+ this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper());
}
@Override
public void handleMessage(Message message) {
- NetworkRequest request = getObject(message, NetworkRequest.class);
- Network network = getObject(message, Network.class);
+ if (message.what == EXPIRE_LEGACY_REQUEST) {
+ expireRequest((NetworkCapabilities) message.obj, message.arg1);
+ return;
+ }
+
+ final NetworkRequest request = getObject(message, NetworkRequest.class);
+ final Network network = getObject(message, Network.class);
+ final NetworkCallback callback;
+ synchronized (sCallbacks) {
+ callback = sCallbacks.get(request);
+ }
if (DBG) {
Log.d(TAG, getCallbackName(message.what) + " for network " + network);
}
+ if (callback == null) {
+ Log.w(TAG, "callback not found for " + getCallbackName(message.what) + " message");
+ return;
+ }
+
switch (message.what) {
case CALLBACK_PRECHECK: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onPreCheck(network);
- }
+ callback.onPreCheck(network);
break;
}
case CALLBACK_AVAILABLE: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onAvailable(network);
- }
+ callback.onAvailable(network);
break;
}
case CALLBACK_LOSING: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onLosing(network, message.arg1);
- }
+ callback.onLosing(network, message.arg1);
break;
}
case CALLBACK_LOST: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onLost(network);
- }
+ callback.onLost(network);
break;
}
case CALLBACK_UNAVAIL: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onUnavailable();
- }
+ callback.onUnavailable();
break;
}
case CALLBACK_CAP_CHANGED: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
- callback.onCapabilitiesChanged(network, cap);
- }
+ NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
+ callback.onCapabilitiesChanged(network, cap);
break;
}
case CALLBACK_IP_CHANGED: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- LinkProperties lp = getObject(message, LinkProperties.class);
- callback.onLinkPropertiesChanged(network, lp);
- }
+ LinkProperties lp = getObject(message, LinkProperties.class);
+ callback.onLinkPropertiesChanged(network, lp);
break;
}
case CALLBACK_SUSPENDED: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onNetworkSuspended(network);
- }
+ callback.onNetworkSuspended(network);
break;
}
case CALLBACK_RESUMED: {
- NetworkCallback callback = getCallback(message);
- if (callback != null) {
- callback.onNetworkResumed(network);
- }
- break;
- }
- case EXPIRE_LEGACY_REQUEST: {
- expireRequest((NetworkCapabilities)message.obj, message.arg1);
+ callback.onNetworkResumed(network);
break;
}
}
@@ -2858,18 +2837,6 @@
private <T> T getObject(Message msg, Class<T> c) {
return (T) msg.getData().getParcelable(c.getSimpleName());
}
-
- private NetworkCallback getCallback(Message msg) {
- final NetworkRequest req = getObject(msg, NetworkRequest.class);
- final NetworkCallback callback;
- synchronized(sCallbacks) {
- callback = sCallbacks.get(req);
- }
- if (callback == null) {
- Log.w(TAG, "callback not found for " + getCallbackName(msg.what) + " message");
- }
- return callback;
- }
}
private CallbackHandler getDefaultHandler() {
@@ -2889,7 +2856,7 @@
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
int timeoutMs, int action, int legacyType, CallbackHandler handler) {
- Preconditions.checkArgument(callback != null, "null NetworkCallback");
+ checkCallbackNotNull(callback);
Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities");
final NetworkRequest request;
try {
@@ -2944,7 +2911,7 @@
* This {@link NetworkRequest} will live until released via
* {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits. A
* version of the method which takes a timeout is
- * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)}.
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}.
* Status of the request can be followed by listening to the various
* callbacks described in {@link NetworkCallback}. The {@link Network}
* can be used to direct traffic to the network.
@@ -2979,7 +2946,7 @@
* This {@link NetworkRequest} will live until released via
* {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits. A
* version of the method which takes a timeout is
- * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)}.
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}.
* Status of the request can be followed by listening to the various
* callbacks described in {@link NetworkCallback}. The {@link Network}
* can be used to direct traffic to the network.
@@ -3012,50 +2979,6 @@
}
/**
- * Note: this is a deprecated version of
- * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)} - please transition code to use
- * the unhidden version of the function.
- * TODO: replace all callers with the new version of the API
- *
- * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
- * by a timeout.
- *
- * This function behaves identically to the non-timed-out version
- * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, but if a suitable network
- * is not found within the given time (in milliseconds) the
- * {@link NetworkCallback#onUnavailable()} callback is called. The request can still be
- * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does
- * not have to be released if timed-out (it is automatically released). Unregistering a
- * request that timed out is not an error.
- *
- * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small
- * timeout) - the {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided
- * for that purpose. Calling this method will attempt to bring up the requested network.
- *
- * <p>This method requires the caller to hold either the
- * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
- * or the ability to modify system settings as determined by
- * {@link android.provider.Settings.System#canWrite}.</p>
- *
- * @param request {@link NetworkRequest} describing this request.
- * @param networkCallback The callbacks to be utilized for this request. Note
- * the callbacks must not be shared - they uniquely specify
- * this request.
- * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
- * before {@link NetworkCallback#onUnavailable()} is called. The timeout must
- * be a positive value (i.e. >0).
- * @hide
- */
- public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
- int timeoutMs) {
- if (timeoutMs <= 0) {
- throw new IllegalArgumentException("Non-positive timeoutMs: " + timeoutMs);
- }
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
- requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
- }
-
- /**
* Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
* by a timeout.
*
@@ -3077,22 +3000,19 @@
* {@link android.provider.Settings.System#canWrite}.</p>
*
* @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
* @param timeoutMs The time in milliseconds to attempt looking for a suitable network
* before {@link NetworkCallback#onUnavailable()} is called. The timeout must
* be a positive value (i.e. >0).
- * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
- * the callback must not be shared - it uniquely specifies this request.
*/
- public void requestNetwork(NetworkRequest request, int timeoutMs,
- NetworkCallback networkCallback) {
- if (timeoutMs <= 0) {
- throw new IllegalArgumentException("Non-positive timeoutMs: " + timeoutMs);
- }
+ public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
+ int timeoutMs) {
+ checkTimeout(timeoutMs);
int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
}
-
/**
* Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
* by a timeout.
@@ -3114,17 +3034,15 @@
* {@link android.provider.Settings.System#canWrite}.</p>
*
* @param request {@link NetworkRequest} describing this request.
- * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
- * before {@link NetworkCallback#onUnavailable} is called.
* @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
* the callback must not be shared - it uniquely specifies this request.
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
+ * before {@link NetworkCallback#onUnavailable} is called.
*/
- public void requestNetwork(NetworkRequest request, int timeoutMs,
- NetworkCallback networkCallback, Handler handler) {
- if (timeoutMs <= 0) {
- throw new IllegalArgumentException("Non-positive timeoutMs");
- }
+ public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
+ Handler handler, int timeoutMs) {
+ checkTimeout(timeoutMs);
int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
CallbackHandler cbHandler = new CallbackHandler(handler);
requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler);
@@ -3196,7 +3114,7 @@
* {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}.
*/
public void requestNetwork(NetworkRequest request, PendingIntent operation) {
- checkPendingIntent(operation);
+ checkPendingIntentNotNull(operation);
try {
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {
@@ -3219,7 +3137,7 @@
* corresponding NetworkRequest you'd like to remove. Cannot be null.
*/
public void releaseNetworkRequest(PendingIntent operation) {
- checkPendingIntent(operation);
+ checkPendingIntentNotNull(operation);
try {
mService.releasePendingNetworkRequest(operation);
} catch (RemoteException e) {
@@ -3227,10 +3145,16 @@
}
}
- private void checkPendingIntent(PendingIntent intent) {
- if (intent == null) {
- throw new IllegalArgumentException("PendingIntent cannot be null.");
- }
+ private static void checkPendingIntentNotNull(PendingIntent intent) {
+ Preconditions.checkNotNull(intent, "PendingIntent cannot be null.");
+ }
+
+ private static void checkCallbackNotNull(NetworkCallback callback) {
+ Preconditions.checkNotNull(callback, "null NetworkCallback");
+ }
+
+ private static void checkTimeout(int timeoutMs) {
+ Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive.");
}
/**
@@ -3300,7 +3224,7 @@
* comes from {@link PendingIntent#getBroadcast}. Cannot be null.
*/
public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) {
- checkPendingIntent(operation);
+ checkPendingIntentNotNull(operation);
try {
mService.pendingListenForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {
@@ -3344,8 +3268,9 @@
// capabilities, this request is guaranteed, at all times, to be
// satisfied by the same network, if any, that satisfies the default
// request, i.e., the system default network.
+ NetworkCapabilities nullCapabilities = null;
CallbackHandler cbHandler = new CallbackHandler(handler);
- sendRequestForNetwork(null, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler);
+ sendRequestForNetwork(nullCapabilities, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler);
}
/**
@@ -3382,7 +3307,7 @@
* @param networkCallback The {@link NetworkCallback} used when making the request.
*/
public void unregisterNetworkCallback(NetworkCallback networkCallback) {
- Preconditions.checkArgument(networkCallback != null, "null NetworkCallback");
+ checkCallbackNotNull(networkCallback);
final List<NetworkRequest> reqs = new ArrayList<>();
// Find all requests associated to this callback and stop callback triggers immediately.
// Callback is reusable immediately. http://b/20701525, http://b/35921499.
@@ -3418,6 +3343,7 @@
* Cannot be null.
*/
public void unregisterNetworkCallback(PendingIntent operation) {
+ checkPendingIntentNotNull(operation);
releaseNetworkRequest(operation);
}
@@ -3468,10 +3394,26 @@
}
/**
+ * Requests that the system open the captive portal app on the specified network.
+ *
+ * @param network The network to log into.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+ public void startCaptivePortalApp(Network network) {
+ try {
+ mService.startCaptivePortalApp(network);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* It is acceptable to briefly use multipath data to provide seamless connectivity for
* time-sensitive user-facing operations when the system default network is temporarily
- * unresponsive. The amount of data should be limited (less than one megabyte), and the
- * operation should be infrequent to ensure that data usage is limited.
+ * unresponsive. The amount of data should be limited (less than one megabyte for every call to
+ * this method), and the operation should be infrequent to ensure that data usage is limited.
*
* An example of such an operation might be a time-sensitive foreground activity, such as a
* voice command, that the user is performing while walking out of range of a Wi-Fi network.
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 63a1f051..27729dc 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -161,6 +161,7 @@
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
void setAvoidUnvalidated(in Network network);
+ void startCaptivePortalApp(in Network network);
int getMultipathPreference(in Network Network);
diff --git a/nfc-extras/Android.mk b/nfc-extras/Android.mk
index cd7a45b..dc45a50 100644
--- a/nfc-extras/Android.mk
+++ b/nfc-extras/Android.mk
@@ -4,10 +4,10 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_MODULE:= com.android.nfc_extras
include $(BUILD_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
index 3eca76d..d8fe5a6 100644
--- a/nfc-extras/tests/Android.mk
+++ b/nfc-extras/tests/Android.mk
@@ -22,6 +22,8 @@
android.test.runner \
com.android.nfc_extras
+LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/obex/javax/obex/ApplicationParameter.java b/obex/javax/obex/ApplicationParameter.java
index a62210f..16770a1a 100644
--- a/obex/javax/obex/ApplicationParameter.java
+++ b/obex/javax/obex/ApplicationParameter.java
@@ -55,7 +55,7 @@
public static final byte LISTSTARTOFFSET_TAGID = 0x05;
- public static final byte FILTER_TAGID = 0x06;
+ public static final byte PROPERTY_SELECTOR_TAGID = 0x06;
public static final byte FORMAT_TAGID = 0x07;
@@ -64,6 +64,20 @@
// only used in "mch" in response
public static final byte NEWMISSEDCALLS_TAGID = 0x09;
+
+ public static final byte SUPPORTEDFEATURE_TAGID = 0x10;
+
+ public static final byte PRIMARYVERSIONCOUNTER_TAGID = 0x0A;
+
+ public static final byte SECONDARYVERSIONCOUNTER_TAGID = 0x0B;
+
+ public static final byte VCARDSELECTOR_TAGID = 0x0C;
+
+ public static final byte DATABASEIDENTIFIER_TAGID = 0x0D;
+
+ public static final byte VCARDSELECTOROPERATOR_TAGID = 0x0E;
+
+ public static final byte RESET_NEW_MISSED_CALLS_TAGID = 0x0F;
}
public static class TRIPLET_VALUE {
@@ -99,13 +113,27 @@
public static final byte LISTSTARTOFFSET_LENGTH = 2;
- public static final byte FILTER_LENGTH = 8;
+ public static final byte PROPERTY_SELECTOR_LENGTH = 8;
public static final byte FORMAT_LENGTH = 1;
public static final byte PHONEBOOKSIZE_LENGTH = 2;
public static final byte NEWMISSEDCALLS_LENGTH = 1;
+
+ public static final byte SUPPORTEDFEATURE_LENGTH = 4;
+
+ public static final byte PRIMARYVERSIONCOUNTER_LENGTH = 16;
+
+ public static final byte SECONDARYVERSIONCOUNTER_LENGTH = 16;
+
+ public static final byte VCARDSELECTOR_LENGTH = 8;
+
+ public static final byte DATABASEIDENTIFIER_LENGTH = 16;
+
+ public static final byte VCARDSELECTOROPERATOR_LENGTH = 1;
+
+ public static final byte RESETNEWMISSEDCALLS_LENGTH = 1;
}
public ApplicationParameter() {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 19badbd..7b4981e4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2764,6 +2764,17 @@
PROMPT_UNVALIDATED_DELAY_MS);
}
+ @Override
+ public void startCaptivePortalApp(Network network) {
+ enforceConnectivityInternalPermission();
+ mHandler.post(() -> {
+ NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai == null) return;
+ if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
+ nai.networkMonitor.sendMessage(NetworkMonitor.CMD_LAUNCH_CAPTIVE_PORTAL_APP);
+ });
+ }
+
public boolean avoidBadWifi() {
return mMultinetworkPolicyTracker.getAvoidBadWifi();
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 7e1a1ca..ac2f4d0 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -149,7 +149,7 @@
*/
public static final String PERMISSION_SYSTEM = "SYSTEM";
- class NetdResponseCode {
+ static class NetdResponseCode {
/* Keep in sync with system/netd/server/ResponseCode.h */
public static final int InterfaceListResult = 110;
public static final int TetherInterfaceListResult = 111;
@@ -220,7 +220,7 @@
private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
- private Object mQuotaLock = new Object();
+ private final Object mQuotaLock = new Object();
/** Set of interfaces with active quotas. */
@GuardedBy("mQuotaLock")
@@ -265,7 +265,7 @@
@GuardedBy("mQuotaLock")
private boolean mDataSaverMode;
- private Object mIdleTimerLock = new Object();
+ private final Object mIdleTimerLock = new Object();
/** Set of interfaces with active idle timers. */
private static class IdleTimerParams {
public final int timeout;
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index b41bcec..66347e6 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -197,11 +197,13 @@
public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 10;
/**
- * Message to self indicating sign-in app should be launched.
+ * Message indicating sign-in app should be launched.
* Sent by mLaunchCaptivePortalAppBroadcastReceiver when the
- * user touches the sign in notification.
+ * user touches the sign in notification, or sent by
+ * ConnectivityService when the user touches the "sign into
+ * network" button in the wifi access point detail page.
*/
- private static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
+ public static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
/**
* Retest network to see if captive portal is still in place.
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 3c46226..ee89d57 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -241,21 +241,11 @@
// See NetlinkHandler.cpp:71.
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
synchronized (mPublicSync) {
- int interfaceType = ifaceNameToType(iface);
- if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
- return;
- }
-
- TetherState tetherState = mTetherStates.get(iface);
if (up) {
- if (tetherState == null) {
- trackNewTetherableInterface(iface, interfaceType);
- }
+ maybeTrackNewInterfaceLocked(iface);
} else {
- if (interfaceType == ConnectivityManager.TETHERING_BLUETOOTH) {
- tetherState.stateMachine.sendMessage(
- TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
- mTetherStates.remove(iface);
+ if (ifaceNameToType(iface) == ConnectivityManager.TETHERING_BLUETOOTH) {
+ stopTrackingInterfaceLocked(iface);
} else {
// Ignore usb0 down after enabling RNDIS.
// We will handle disconnect in interfaceRemoved.
@@ -289,18 +279,7 @@
public void interfaceAdded(String iface) {
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
synchronized (mPublicSync) {
- int interfaceType = ifaceNameToType(iface);
- if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
- if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
- return;
- }
-
- TetherState tetherState = mTetherStates.get(iface);
- if (tetherState == null) {
- trackNewTetherableInterface(iface, interfaceType);
- } else {
- if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
- }
+ maybeTrackNewInterfaceLocked(iface);
}
}
@@ -308,15 +287,7 @@
public void interfaceRemoved(String iface) {
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mPublicSync) {
- TetherState tetherState = mTetherStates.get(iface);
- if (tetherState == null) {
- if (VDBG) {
- Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
- }
- return;
- }
- tetherState.stateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
- mTetherStates.remove(iface);
+ stopTrackingInterfaceLocked(iface);
}
}
@@ -755,7 +726,7 @@
mLastNotificationId = icon;
notificationManager.notifyAsUser(null, mLastNotificationId,
- mTetheredNotificationBuilder.build(), UserHandle.ALL);
+ mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
}
private void clearTetheredNotification() {
@@ -1774,15 +1745,40 @@
sendTetherStateChangedBroadcast();
}
- private void trackNewTetherableInterface(String iface, int interfaceType) {
- TetherState tetherState;
- tetherState = new TetherState(new TetherInterfaceStateMachine(iface, mLooper,
- interfaceType, mLog, mNMService, mStatsService, this,
- new IPv6TetheringInterfaceServices(iface, mNMService, mLog)));
+ private void maybeTrackNewInterfaceLocked(final String iface) {
+ // If we don't care about this type of interface, ignore.
+ final int interfaceType = ifaceNameToType(iface);
+ if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
+ mLog.log(iface + " is not a tetherable iface, ignoring");
+ return;
+ }
+
+ // If we have already started a TISM for this interface, skip.
+ if (mTetherStates.containsKey(iface)) {
+ mLog.log("active iface (" + iface + ") reported as added, ignoring");
+ return;
+ }
+
+ mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
+ final TetherState tetherState = new TetherState(
+ new TetherInterfaceStateMachine(
+ iface, mLooper, interfaceType, mLog, mNMService, mStatsService, this,
+ new IPv6TetheringInterfaceServices(iface, mNMService, mLog)));
mTetherStates.put(iface, tetherState);
tetherState.stateMachine.start();
}
+ private void stopTrackingInterfaceLocked(final String iface) {
+ final TetherState tetherState = mTetherStates.get(iface);
+ if (tetherState == null) {
+ mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
+ return;
+ }
+ tetherState.stateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
+ mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
+ mTetherStates.remove(iface);
+ }
+
private static String[] copy(String[] strarray) {
return Arrays.copyOf(strarray, strarray.length);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 44c61f0..6941193 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -163,20 +163,31 @@
}
// Fix up upstream interface types for DUN or mobile. NOTE: independent
- // of the value of |requiresDun|, cell data of one form or another is
+ // of the value of |dunCheck|, cell data of one form or another is
// *always* an upstream, regardless of the upstream interface types
// specified by configuration resources.
if (dunCheck == DUN_REQUIRED) {
if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
}
- } else {
+ } else if (dunCheck == DUN_NOT_REQUIRED) {
if (!upstreamIfaceTypes.contains(TYPE_MOBILE)) {
upstreamIfaceTypes.add(TYPE_MOBILE);
}
if (!upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)) {
upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
}
+ } else {
+ // Fix upstream interface types for case DUN_UNSPECIFIED.
+ // Do not modify if a cellular interface type is already present in the
+ // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no
+ // cellular interface types are found in the upstream interface types.
+ if (!(upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)
+ || upstreamIfaceTypes.contains(TYPE_MOBILE)
+ || upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI))) {
+ upstreamIfaceTypes.add(TYPE_MOBILE);
+ upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
+ }
}
return upstreamIfaceTypes;
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
index 98771df..a91fe77 100644
--- a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -219,6 +219,7 @@
List<SubscriptionInfo> activeSubscriptionInfoList =
mSubscriptionManager.getActiveSubscriptionInfoList();
if (activeSubscriptionInfoList == null) {
+ setSimNeedsEmergencyAffordance(neededNow);
return neededNow;
}
for (SubscriptionInfo info : activeSubscriptionInfoList) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index df7c660..9949af3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -847,8 +847,8 @@
public void update(Uri uri) {
ContentResolver resolver = getContext().getContentResolver();
if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
- boolean pulseEnabled = Settings.System.getInt(resolver,
- Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0;
+ boolean pulseEnabled = Settings.System.getIntForUser(resolver,
+ Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0;
if (mNotificationPulseEnabled != pulseEnabled) {
mNotificationPulseEnabled = pulseEnabled;
updateNotificationPulse();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7d22a2c..e3d66e7 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -574,11 +574,19 @@
public static final String KEY_CARRIER_METERED_APN_TYPES_STRINGS =
"carrier_metered_apn_types_strings";
/**
- * Default APN types that are roamig-metered by the carrier
+ * Default APN types that are roaming-metered by the carrier
* @hide
*/
public static final String KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS =
"carrier_metered_roaming_apn_types_strings";
+
+ /**
+ * Default APN types that are metered on IWLAN by the carrier
+ * @hide
+ */
+ public static final String KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS =
+ "carrier_metered_iwlan_apn_types_strings";
+
/**
* CDMA carrier ERI (Enhanced Roaming Indicator) file name
* @hide
@@ -1443,6 +1451,9 @@
new String[]{"default", "mms", "dun", "supl"});
sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
+ // By default all APNs are unmetered if the device is on IWLAN.
+ sDefaults.putStringArray(KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS,
+ new String[]{});
sDefaults.putIntArray(KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY,
new int[]{
diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java
index 251d5bb..6754426 100644
--- a/telephony/java/android/telephony/MbmsStreamingManager.java
+++ b/telephony/java/android/telephony/MbmsStreamingManager.java
@@ -22,6 +22,7 @@
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.mbms.MbmsException;
@@ -157,6 +158,7 @@
* {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
* {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
* {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
+ * {@link MbmsException#ERROR_SERVICE_LOST}
*
* Asynchronous error codes via the {@link MbmsStreamingManagerCallback#error(int, String)}
* callback can include any of the errors except:
@@ -172,6 +174,10 @@
if (returnCode != MbmsException.SUCCESS) {
throw new MbmsException(returnCode);
}
+ } catch (DeadObjectException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
} catch (RemoteException e) {
throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
}
@@ -187,6 +193,7 @@
* {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
* {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
* {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
+ * {@link MbmsException#ERROR_SERVICE_LOST}
*
* May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
*
@@ -204,6 +211,10 @@
if (returnCode != MbmsException.SUCCESS) {
throw new MbmsException(returnCode);
}
+ } catch (DeadObjectException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
} catch (RemoteException e) {
throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
}
@@ -269,7 +280,11 @@
} catch (RemoteException e) {
mService = null;
Log.e(LOG_TAG, "Service died before initialization");
- throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+ if (e instanceof DeadObjectException) {
+ throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
+ } else {
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+ }
}
}
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index bc5e4d5..07259cf 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -3093,34 +3093,20 @@
/*
* The config held calling number conversion map, expected to convert to emergency number.
*/
- private static final String[] CONVERT_TO_EMERGENCY_MAP = Resources.getSystem().getStringArray(
- com.android.internal.R.array.config_convert_to_emergency_number_map);
- /**
- * Check whether conversion to emergency number is enabled
- *
- * @return {@code true} when conversion to emergency numbers is enabled,
- * {@code false} otherwise
- *
- * @hide
- */
- public static boolean isConvertToEmergencyNumberEnabled() {
- return CONVERT_TO_EMERGENCY_MAP != null && CONVERT_TO_EMERGENCY_MAP.length > 0;
- }
+ private static String[] sConvertToEmergencyMap = null;
/**
* Converts to emergency number based on the conversion map.
* The conversion map is declared as config_convert_to_emergency_number_map.
*
- * Make sure {@link #isConvertToEmergencyNumberEnabled} is true before calling
- * this function.
- *
+ * @param context a context to use for accessing resources
* @return The converted emergency number if the number matches conversion map,
* otherwise original number.
*
* @hide
*/
- public static String convertToEmergencyNumber(String number) {
- if (TextUtils.isEmpty(number)) {
+ public static String convertToEmergencyNumber(Context context, String number) {
+ if (context == null || TextUtils.isEmpty(number)) {
return number;
}
@@ -3131,7 +3117,17 @@
return number;
}
- for (String convertMap : CONVERT_TO_EMERGENCY_MAP) {
+ if (sConvertToEmergencyMap == null) {
+ sConvertToEmergencyMap = context.getResources().getStringArray(
+ com.android.internal.R.array.config_convert_to_emergency_number_map);
+ }
+
+ // The conversion map is not defined (this is default). Skip conversion.
+ if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0 ) {
+ return number;
+ }
+
+ for (String convertMap : sConvertToEmergencyMap) {
if (DBG) log("convertToEmergencyNumber: " + convertMap);
String[] entry = null;
String[] filterNumbers = null;
diff --git a/telephony/java/android/telephony/mbms/MbmsException.java b/telephony/java/android/telephony/mbms/MbmsException.java
index a0ded9b..ac14c4f 100644
--- a/telephony/java/android/telephony/mbms/MbmsException.java
+++ b/telephony/java/android/telephony/mbms/MbmsException.java
@@ -29,6 +29,7 @@
public static final int ERROR_UNABLE_TO_START_SERVICE = 8;
public static final int ERROR_STREAM_ALREADY_STARTED = 9;
public static final int ERROR_END_OF_SESSION = 10;
+ public static final int ERROR_SERVICE_LOST = 11;
private final int mErrorCode;
diff --git a/telephony/java/android/telephony/mbms/StreamingService.java b/telephony/java/android/telephony/mbms/StreamingService.java
index ac5fbdf..745cb98 100644
--- a/telephony/java/android/telephony/mbms/StreamingService.java
+++ b/telephony/java/android/telephony/mbms/StreamingService.java
@@ -17,8 +17,7 @@
package android.telephony.mbms;
import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.DeadObjectException;
import android.os.RemoteException;
import android.telephony.mbms.vendor.IMbmsStreamingService;
import android.util.Log;
@@ -34,9 +33,10 @@
private final String mAppName;
private final int mSubscriptionId;
- private final IMbmsStreamingService mService;
private final StreamingServiceInfo mServiceInfo;
private final IStreamingServiceCallback mCallback;
+
+ private IMbmsStreamingService mService;
/**
* @hide
*/
@@ -55,13 +55,23 @@
/**
* Retreive the Uri used to play this stream.
*
- * This may throw a {@link MbmsException} with the error code
- * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
+ * This may throw a {@link MbmsException} with the error codes
+ * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION} or
+ * {@link MbmsException#ERROR_SERVICE_LOST}
+ *
* @return The {@link Uri} to pass to the streaming client.
*/
public Uri getPlaybackUri() throws MbmsException {
+ if (mService == null) {
+ throw new IllegalStateException("No streaming service attached");
+ }
+
try {
return mService.getPlaybackUri(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+ } catch (DeadObjectException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Caught remote exception calling getPlaybackUri: " + e);
throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
@@ -76,18 +86,41 @@
}
/**
- * Stop streaming this service. Terminal.
- *
- * This may throw a RemoteException.
+ * Stop streaming this service.
+ * This may throw a {@link MbmsException} with the error code
+ * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION} or
+ * {@link MbmsException#ERROR_SERVICE_LOST}
*/
- public void stopStreaming() {
+ public void stopStreaming() throws MbmsException {
+ if (mService == null) {
+ throw new IllegalStateException("No streaming service attached");
+ }
+
+ try {
+ mService.stopStreaming(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+ } catch (DeadObjectException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Caught remote exception calling stopStreaming: " + e);
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+ }
}
public void dispose() throws MbmsException {
+ if (mService == null) {
+ throw new IllegalStateException("No streaming service attached");
+ }
+
try {
mService.disposeStream(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+ } catch (DeadObjectException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "Caught remote exception calling disposeStream: " + e);
+ Log.w(LOG_TAG, "Caught remote exception calling dispose: " + e);
throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
}
}
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index 37f47ff..5b74312 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -107,15 +107,44 @@
return null;
}
+ /**
+ * Stop streaming the stream identified by {@code serviceId}. Notification of the resulting
+ * stream state change should be reported to the app via
+ * {@link IStreamingServiceCallback#streamStateChanged(int)}.
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription id to use.
+ * @param serviceId The ID of the streaming service that the app wishes to stop.
+ */
@Override
- public void stopStreaming(String appName, int subId, String serviceId) throws RemoteException {
+ public void stopStreaming(String appName, int subscriptionId, String serviceId)
+ throws RemoteException {
}
+ /**
+ * Dispose of the stream identified by {@code serviceId} for the app identified by the
+ * {@code appName} and {@code subscriptionId} arguments along with the caller's uid.
+ * No notification back to the app is required for this operation, and the callback provided via
+ * {@link #startStreaming(String, int, String, IStreamingServiceCallback)} should no longer be
+ * used after this method has called by the app.
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription id to use.
+ * @param serviceId The ID of the streaming service that the app wishes to dispose of.
+ */
@Override
- public void disposeStream(String appName, int subId, String serviceId) throws RemoteException {
+ public void disposeStream(String appName, int subscriptionId, String serviceId)
+ throws RemoteException {
}
+ /**
+ * Signals that the app wishes to dispose of the session identified by the {@code appName} and
+ * {@code subscriptionId} arguments, as well as the caller's uid. No notification back to the
+ * app is required for this operation, and the corresponding callback provided via
+ * {@link #initialize(IMbmsStreamingManagerCallback, String, int)} should no longer be used
+ * after this method has been called by the app.
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription id to use.
+ */
@Override
- public void dispose(String appName, int subId) throws RemoteException {
+ public void dispose(String appName, int subscriptionId) throws RemoteException {
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 3c0b8aa..00b0f98 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -39,6 +39,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.net.CaptivePortal;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -78,6 +79,7 @@
import android.os.Parcelable;
import android.os.Process;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
@@ -113,7 +115,7 @@
* Tests for {@link ConnectivityService}.
*
* Build, install and run with:
- * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
+ * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
*/
public class ConnectivityServiceTest extends AndroidTestCase {
private static final String TAG = "ConnectivityServiceTest";
@@ -121,7 +123,7 @@
private static final int TIMEOUT_MS = 500;
private static final int TEST_LINGER_DELAY_MS = 120;
- private BroadcastInterceptingContext mServiceContext;
+ private MockContext mServiceContext;
private WrappedConnectivityService mService;
private WrappedConnectivityManager mCm;
private MockNetworkAgent mWiFiNetworkAgent;
@@ -152,6 +154,7 @@
private final MockContentResolver mContentResolver;
@Spy private Resources mResources;
+ private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
MockContext(Context base) {
super(base);
@@ -169,6 +172,27 @@
}
@Override
+ public void startActivityAsUser(Intent intent, UserHandle handle) {
+ mStartedActivities.offer(intent);
+ }
+
+ public Intent expectStartActivityIntent(int timeoutMs) {
+ Intent intent = null;
+ try {
+ intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {}
+ assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
+ return intent;
+ }
+
+ public void expectNoStartActivityIntent(int timeoutMs) {
+ try {
+ assertNull("Received unexpected Intent to start activity",
+ mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {}
+ }
+
+ @Override
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
@@ -199,13 +223,32 @@
}
}
+ public void waitForIdle(int timeoutMs) {
+ waitForIdleHandler(mService.mHandlerThread, timeoutMs);
+ waitForIdle(mCellNetworkAgent, timeoutMs);
+ waitForIdle(mWiFiNetworkAgent, timeoutMs);
+ waitForIdle(mEthernetNetworkAgent, timeoutMs);
+ waitForIdleHandler(mService.mHandlerThread, timeoutMs);
+ }
+
+ public void waitForIdle(MockNetworkAgent agent, int timeoutMs) {
+ if (agent == null) {
+ return;
+ }
+ waitForIdleHandler(agent.mHandlerThread, timeoutMs);
+ }
+
+ private void waitForIdle() {
+ waitForIdle(TIMEOUT_MS);
+ }
+
@SmallTest
public void testWaitForIdle() {
final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
// Tests that waitForIdle returns immediately if the service is already idle.
for (int i = 0; i < attempts; i++) {
- mService.waitForIdle();
+ waitForIdle();
}
// Bring up a network that we can use to send messages to ConnectivityService.
@@ -219,7 +262,7 @@
// Tests that calling waitForIdle waits for messages to be processed.
for (int i = 0; i < attempts; i++) {
mWiFiNetworkAgent.setSignalStrength(i);
- mService.waitForIdle();
+ waitForIdle();
assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
}
}
@@ -320,23 +363,19 @@
};
// Waits for the NetworkAgent to be registered, which includes the creation of the
// NetworkMonitor.
- mService.waitForIdle();
+ waitForIdle();
mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
}
- public void waitForIdle(int timeoutMs) {
- waitForIdleHandler(mHandlerThread, timeoutMs);
- }
-
- public void waitForIdle() {
- waitForIdle(TIMEOUT_MS);
- }
-
public void adjustScore(int change) {
mScore += change;
mNetworkAgent.sendNetworkScore(mScore);
}
+ public void explicitlySelected(boolean acceptUnvalidated) {
+ mNetworkAgent.explicitlySelected(acceptUnvalidated);
+ }
+
public void addCapability(int capability) {
mNetworkCapabilities.addCapability(capability);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
@@ -769,17 +808,27 @@
// Ensure that the default setting for Captive Portals is used for most tests
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
+ setMobileDataAlwaysOn(false);
}
public void tearDown() throws Exception {
setMobileDataAlwaysOn(false);
- if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
- if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
- mCellNetworkAgent = mWiFiNetworkAgent = null;
+ if (mCellNetworkAgent != null) {
+ mCellNetworkAgent.disconnect();
+ mCellNetworkAgent = null;
+ }
+ if (mWiFiNetworkAgent != null) {
+ mWiFiNetworkAgent.disconnect();
+ mWiFiNetworkAgent = null;
+ }
+ if (mEthernetNetworkAgent != null) {
+ mEthernetNetworkAgent.disconnect();
+ mEthernetNetworkAgent = null;
+ }
super.tearDown();
}
- private int transportToLegacyType(int transport) {
+ private static int transportToLegacyType(int transport) {
switch (transport) {
case TRANSPORT_ETHERNET:
return TYPE_ETHERNET;
@@ -811,7 +860,8 @@
}
// Test getNetworkInfo(Network)
assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
- assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
+ assertEquals(transportToLegacyType(transport),
+ mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
// Test getNetworkCapabilities(Network)
assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
@@ -882,7 +932,7 @@
mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
// Test cellular linger timeout.
waitFor(mCellNetworkAgent.getDisconnectedCV());
- mService.waitForIdle();
+ waitForIdle();
assertEquals(1, mCm.getAllNetworks().length);
verifyActiveNetwork(TRANSPORT_WIFI);
assertEquals(1, mCm.getAllNetworks().length);
@@ -905,11 +955,11 @@
// Test bringing up unvalidated cellular
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
- mService.waitForIdle();
+ waitForIdle();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test cellular disconnect.
mCellNetworkAgent.disconnect();
- mService.waitForIdle();
+ waitForIdle();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1261,7 +1311,7 @@
}
void assertNoCallback() {
- mService.waitForIdle();
+ waitForIdle();
CallbackInfo c = mCallbacks.peek();
assertNull("Unexpected callback: " + c, c);
}
@@ -1302,7 +1352,7 @@
// This should not trigger spurious onAvailable() callbacks, b/21762680.
mCellNetworkAgent.adjustScore(-1);
- mService.waitForIdle();
+ waitForIdle();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1340,7 +1390,7 @@
// This should not trigger spurious onAvailable() callbacks, b/21762680.
mCellNetworkAgent.adjustScore(-1);
- mService.waitForIdle();
+ waitForIdle();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1452,7 +1502,7 @@
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
mCm.unregisterNetworkCallback(callback);
- mService.waitForIdle();
+ waitForIdle();
// Check that a network is only lingered or torn down if it would not satisfy a request even
// if it validated.
@@ -1567,13 +1617,104 @@
final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
+ // Register a TRACK_DEFAULT request and check that it does not affect lingering.
+ TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(trackDefaultCallback);
+ trackDefaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent.connect(true);
+ callback.expectAvailableCallbacks(mEthernetNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
+ callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
+ trackDefaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
+ defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
+
+ // Let linger run its course.
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
+
// Clean up.
- mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ mEthernetNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+ defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+ trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultCallback);
+ mCm.unregisterNetworkCallback(trackDefaultCallback);
+ }
+
+ @SmallTest
+ public void testExplicitlySelected() {
+ NetworkRequest request = new NetworkRequest.Builder()
+ .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, callback);
+
+ // Bring up validated cell.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+
+ // Bring up unvalidated wifi with explicitlySelected=true.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+
+ // Cell Remains the default.
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ // Lower wifi's score to below than cell, and check that it doesn't disconnect because
+ // it's explicitly selected.
+ mWiFiNetworkAgent.adjustScore(-40);
+ mWiFiNetworkAgent.adjustScore(40);
+ callback.assertNoCallback();
+
+ // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
+ // wifi even though it's unvalidated.
+ mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
+ callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+
+ // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
+ // network to disconnect.
+ mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ // Reconnect, again with explicitlySelected=true, but this time validate.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.connect(true);
+ callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ // BUG: the network will no longer linger, even though it's validated and outscored.
+ // TODO: fix this.
+ mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent.connect(true);
+ callback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
+ assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ callback.assertNoCallback();
+
+ // Clean up.
+ mWiFiNetworkAgent.disconnect();
+ mCellNetworkAgent.disconnect();
+ mEthernetNetworkAgent.disconnect();
+
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
}
private void tryNetworkFactoryRequests(int capability) throws Exception {
@@ -1722,26 +1863,30 @@
ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
mCellNetworkAgent.connectWithoutInternet();
waitFor(cv);
- mService.waitForIdle();
+ waitForIdle();
assertEquals(0, mCm.getAllNetworks().length);
verifyNoNetwork();
+
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
+
// Register MMS NetworkRequest
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(builder.build(), networkCallback);
+
// Test bringing up unvalidated cellular with MMS
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mCellNetworkAgent.connectWithoutInternet();
networkCallback.expectAvailableCallbacks(mCellNetworkAgent);
verifyActiveNetwork(TRANSPORT_WIFI);
+
// Test releasing NetworkRequest disconnects cellular with MMS
cv = mCellNetworkAgent.getDisconnectedCV();
mCm.unregisterNetworkCallback(networkCallback);
@@ -1757,17 +1902,20 @@
mCellNetworkAgent.connect(false);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
+
// Register MMS NetworkRequest
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
final TestNetworkCallback networkCallback = new TestNetworkCallback();
mCm.requestNetwork(builder.build(), networkCallback);
+
// Test bringing up MMS cellular network
MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mmsNetworkAgent.connectWithoutInternet();
networkCallback.expectAvailableCallbacks(mmsNetworkAgent);
verifyActiveNetwork(TRANSPORT_CELLULAR);
+
// Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
cv = mmsNetworkAgent.getDisconnectedCV();
mCm.unregisterNetworkCallback(networkCallback);
@@ -1827,6 +1975,52 @@
}
@SmallTest
+ public void testCaptivePortalApp() {
+ final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
+ final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
+ mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
+
+ final TestNetworkCallback validatedCallback = new TestNetworkCallback();
+ final NetworkRequest validatedRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_VALIDATED).build();
+ mCm.registerNetworkCallback(validatedRequest, validatedCallback);
+
+ // Bring up wifi.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ validatedCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
+
+ // Check that calling startCaptivePortalApp does nothing.
+ final int fastTimeoutMs = 100;
+ mCm.startCaptivePortalApp(wifiNetwork);
+ mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
+
+ // Turn into a captive portal.
+ mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
+ mCm.reportNetworkConnectivity(wifiNetwork, false);
+ captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ // Check that startCaptivePortalApp sends the expected intent.
+ mCm.startCaptivePortalApp(wifiNetwork);
+ Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
+ assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
+ assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
+
+ // Have the app report that the captive portal is dismissed, and check that we revalidate.
+ mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
+ CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
+ c.reportCaptivePortalDismissed();
+ validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ mCm.unregisterNetworkCallback(validatedCallback);
+ mCm.unregisterNetworkCallback(captivePortalCallback);
+ }
+
+ @SmallTest
public void testAvoidOrIgnoreCaptivePortals() {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -2128,7 +2322,7 @@
ContentResolver cr = mServiceContext.getContentResolver();
Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
mService.updateMobileDataAlwaysOn();
- mService.waitForIdle();
+ waitForIdle();
}
private boolean isForegroundNetwork(MockNetworkAgent network) {
@@ -2170,7 +2364,7 @@
assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
// When lingering is complete, cell is still there but is now in the background.
- mService.waitForIdle();
+ waitForIdle();
int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
// Expect a network capabilities update sans FOREGROUND.
@@ -2226,6 +2420,11 @@
// and NUM_REQUESTS onAvailable callbacks to fire.
// See how long it took.
final int NUM_REQUESTS = 90;
+ final int REGISTER_TIME_LIMIT_MS = 180;
+ final int CONNECT_TIME_LIMIT_MS = 50;
+ final int SWITCH_TIME_LIMIT_MS = 50;
+ final int UNREGISTER_TIME_LIMIT_MS = 20;
+
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
@@ -2238,14 +2437,12 @@
};
}
- final int REGISTER_TIME_LIMIT_MS = 180;
assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
for (NetworkCallback cb : callbacks) {
mCm.registerNetworkCallback(request, cb);
}
});
- final int CONNECT_TIME_LIMIT_MS = 40;
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
// Don't request that the network validate, because otherwise connect() will block until
// the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
@@ -2253,31 +2450,29 @@
mCellNetworkAgent.connect(false);
long onAvailableDispatchingDuration = durationOf(() -> {
- if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
- fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
- NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
- CONNECT_TIME_LIMIT_MS));
- }
+ awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
});
- Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
- NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
+ Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
+ NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
+ onAvailableDispatchingDuration));
+ assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
+ NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
+ onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
- final int SWITCH_TIME_LIMIT_MS = 40;
- mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
// Give wifi a high enough score that we'll linger cell when wifi comes up.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.adjustScore(40);
mWiFiNetworkAgent.connect(false);
long onLostDispatchingDuration = durationOf(() -> {
- if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
- fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
- NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
- }
+ awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
});
- Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
- NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
+ Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
+ NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
+ assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
+ NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
+ onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
- final int UNREGISTER_TIME_LIMIT_MS = 10;
assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
for (NetworkCallback cb : callbacks) {
mCm.unregisterNetworkCallback(cb);
@@ -2300,9 +2495,7 @@
private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
try {
- if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
- return true;
- }
+ return l.await(timeoutMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {}
return false;
}
@@ -2354,7 +2547,7 @@
assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
// Check that cell data stays up.
- mService.waitForIdle();
+ waitForIdle();
verifyActiveNetwork(TRANSPORT_WIFI);
assertEquals(2, mCm.getAllNetworks().length);
@@ -2383,7 +2576,7 @@
for (int i = 0; i < values.length; i++) {
Settings.Global.putInt(cr, settingName, 1);
tracker.reevaluate();
- mService.waitForIdle();
+ waitForIdle();
String msg = String.format("config=false, setting=%s", values[i]);
assertTrue(mService.avoidBadWifi());
assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
@@ -2393,19 +2586,19 @@
Settings.Global.putInt(cr, settingName, 0);
tracker.reevaluate();
- mService.waitForIdle();
+ waitForIdle();
assertFalse(mService.avoidBadWifi());
assertFalse(tracker.shouldNotifyWifiUnvalidated());
Settings.Global.putInt(cr, settingName, 1);
tracker.reevaluate();
- mService.waitForIdle();
+ waitForIdle();
assertTrue(mService.avoidBadWifi());
assertFalse(tracker.shouldNotifyWifiUnvalidated());
Settings.Global.putString(cr, settingName, null);
tracker.reevaluate();
- mService.waitForIdle();
+ waitForIdle();
assertFalse(mService.avoidBadWifi());
assertTrue(tracker.shouldNotifyWifiUnvalidated());
}
@@ -2548,7 +2741,7 @@
tracker.configMeteredMultipathPreference = config;
Settings.Global.putString(cr, settingName, setting);
tracker.reevaluate();
- mService.waitForIdle();
+ waitForIdle();
final int expected = (setting != null) ? Integer.parseInt(setting) : config;
String msg = String.format("config=%d, setting=%s", config, setting);
@@ -2736,7 +2929,7 @@
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
mWiFiNetworkAgent.sendLinkProperties(lp);
- mService.waitForIdle();
+ waitForIdle();
return mWiFiNetworkAgent.getNetwork();
}
@@ -2815,7 +3008,7 @@
callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
// ... and that stopping it after that has no adverse effects.
- mService.waitForIdle();
+ waitForIdle();
final Network myNetAlias = myNet;
assertNull(mCm.getNetworkCapabilities(myNetAlias));
ka.stop();
@@ -2830,7 +3023,7 @@
ka.stop();
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
- mService.waitForIdle();
+ waitForIdle();
callback.expectStopped();
// Reconnect.
@@ -3031,7 +3224,7 @@
mCm.unregisterNetworkCallback(pendingIntent);
}
pendingIntents.clear();
- mService.waitForIdle(5000);
+ waitForIdle(5000);
// Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
for (int i = 0; i < MAX_REQUESTS; i++) {
@@ -3039,20 +3232,20 @@
mCm.requestNetwork(networkRequest, networkCallback);
mCm.unregisterNetworkCallback(networkCallback);
}
- mService.waitForIdle();
+ waitForIdle();
for (int i = 0; i < MAX_REQUESTS; i++) {
NetworkCallback networkCallback = new NetworkCallback();
mCm.registerNetworkCallback(networkRequest, networkCallback);
mCm.unregisterNetworkCallback(networkCallback);
}
- mService.waitForIdle();
+ waitForIdle();
for (int i = 0; i < MAX_REQUESTS; i++) {
PendingIntent pendingIntent =
PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
mCm.requestNetwork(networkRequest, pendingIntent);
mCm.unregisterNetworkCallback(pendingIntent);
}
- mService.waitForIdle();
+ waitForIdle();
for (int i = 0; i < MAX_REQUESTS; i++) {
PendingIntent pendingIntent =
PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
diff --git a/tests/net/java/android/net/nsd/NsdServiceTest.java b/tests/net/java/com/android/server/NsdServiceTest.java
similarity index 100%
rename from tests/net/java/android/net/nsd/NsdServiceTest.java
rename to tests/net/java/com/android/server/NsdServiceTest.java
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index 9fcd1b5..ddceea2 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -128,5 +128,8 @@
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
// Just to prove we haven't clobbered Wi-Fi:
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ // Check that we have not added new cellular interface types
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
}
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
index e6b1c6d..23318c2 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
@@ -16,6 +16,7 @@
package com.android.server.net;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import android.Manifest;
@@ -26,17 +27,21 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
import com.android.server.LocalServices;
-import junit.framework.TestCase;
-
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@RunWith(AndroidJUnit4.class)
@SmallTest
-public class NetworkStatsAccessTest extends TestCase {
+public class NetworkStatsAccessTest {
private static final String TEST_PKG = "com.example.test";
private static final int TEST_UID = 12345;
@@ -48,9 +53,8 @@
// Hold the real service so we can restore it when tearing down the test.
private DevicePolicyManagerInternal mSystemDpmi;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
MockitoAnnotations.initMocks(this);
mSystemDpmi = LocalServices.getService(DevicePolicyManagerInternal.class);
@@ -61,13 +65,13 @@
when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOps);
}
- @Override
+ @After
public void tearDown() throws Exception {
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
LocalServices.addService(DevicePolicyManagerInternal.class, mSystemDpmi);
- super.tearDown();
}
+ @Test
public void testCheckAccessLevel_hasCarrierPrivileges() throws Exception {
setHasCarrierPrivileges(true);
setIsDeviceOwner(false);
@@ -78,6 +82,7 @@
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_isDeviceOwner() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(true);
@@ -88,6 +93,7 @@
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_isProfileOwner() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
@@ -98,36 +104,40 @@
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_hasAppOpsBitAllowed() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
setIsProfileOwner(true);
setHasAppOpsPermission(AppOpsManager.MODE_ALLOWED, false);
setHasReadHistoryPermission(false);
- assertEquals(NetworkStatsAccess.Level.USER,
+ assertEquals(NetworkStatsAccess.Level.DEVICESUMMARY,
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_hasAppOpsBitDefault_grantedPermission() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
setIsProfileOwner(true);
setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, true);
setHasReadHistoryPermission(false);
- assertEquals(NetworkStatsAccess.Level.USER,
+ assertEquals(NetworkStatsAccess.Level.DEVICESUMMARY,
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_hasReadHistoryPermission() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
setIsProfileOwner(true);
setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false);
setHasReadHistoryPermission(true);
- assertEquals(NetworkStatsAccess.Level.USER,
+ assertEquals(NetworkStatsAccess.Level.DEVICESUMMARY,
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_deniedAppOpsBit() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
@@ -138,6 +148,7 @@
NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG));
}
+ @Test
public void testCheckAccessLevel_deniedAppOpsBit_deniedPermission() throws Exception {
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index fe7840d..92dcdac 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -18,21 +18,23 @@
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.when;
-
-import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.ROAMING_NO;
+import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.when;
+
import android.app.usage.NetworkStatsManager;
import android.net.DataUsageRequest;
import android.net.NetworkIdentity;
@@ -48,6 +50,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
@@ -60,8 +63,9 @@
import java.util.Objects;
import java.util.List;
-import junit.framework.TestCase;
-
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -69,8 +73,9 @@
/**
* Tests for {@link NetworkStatsObservers}.
*/
+@RunWith(AndroidJUnit4.class)
@SmallTest
-public class NetworkStatsObserversTest extends TestCase {
+public class NetworkStatsObserversTest {
private static final String TEST_IFACE = "test0";
private static final String TEST_IFACE2 = "test1";
private static final long TEST_START = 1194220800000L;
@@ -88,7 +93,7 @@
private static final int UID_GREEN = UserHandle.PER_USER_RANGE + 3;
private static final int UID_ANOTHER_USER = 2 * UserHandle.PER_USER_RANGE + 4;
- private static final long WAIT_TIMEOUT = 500; // 1/2 sec
+ private static final long WAIT_TIMEOUT_MS = 500;
private static final long THRESHOLD_BYTES = 2 * MB_IN_BYTES;
private static final long BASE_BYTES = 7 * MB_IN_BYTES;
private static final int INVALID_TYPE = -1;
@@ -101,7 +106,6 @@
private Handler mObserverNoopHandler;
private LatchedHandler mHandler;
- private ConditionVariable mCv;
private NetworkStatsObservers mStatsObservers;
private Messenger mMessenger;
@@ -110,9 +114,8 @@
@Mock private IBinder mockBinder;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
MockitoAnnotations.initMocks(this);
mObserverHandlerThread = new IdleableHandlerThread("HandlerThread");
@@ -125,14 +128,14 @@
}
};
- mCv = new ConditionVariable();
- mHandler = new LatchedHandler(Looper.getMainLooper(), mCv);
+ mHandler = new LatchedHandler(Looper.getMainLooper(), new ConditionVariable());
mMessenger = new Messenger(mHandler);
mActiveIfaces = new ArrayMap<>();
mActiveUidIfaces = new ArrayMap<>();
}
+ @Test
public void testRegister_thresholdTooLow_setsDefaultThreshold() throws Exception {
long thresholdTooLowBytes = 1L;
DataUsageRequest inputRequest = new DataUsageRequest(
@@ -145,6 +148,7 @@
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
}
+ @Test
public void testRegister_highThreshold_accepted() throws Exception {
long highThresholdBytes = 2 * THRESHOLD_BYTES;
DataUsageRequest inputRequest = new DataUsageRequest(
@@ -157,6 +161,7 @@
assertEquals(highThresholdBytes, request.thresholdInBytes);
}
+ @Test
public void testRegister_twoRequests_twoIds() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, THRESHOLD_BYTES);
@@ -174,6 +179,7 @@
assertEquals(THRESHOLD_BYTES, request2.thresholdInBytes);
}
+ @Test
public void testUnregister_unknownRequest_noop() throws Exception {
DataUsageRequest unknownRequest = new DataUsageRequest(
123456 /* id */, sTemplateWifi, THRESHOLD_BYTES);
@@ -181,6 +187,7 @@
mStatsObservers.unregister(unknownRequest, UID_RED);
}
+ @Test
public void testUnregister_knownRequest_releasesCaller() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -198,6 +205,7 @@
Mockito.verify(mockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt());
}
+ @Test
public void testUnregister_knownRequest_invalidUid_doesNotUnregister() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -215,6 +223,7 @@
Mockito.verifyZeroInteractions(mockBinder);
}
+ @Test
public void testUpdateStats_initialSample_doesNotNotify() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -240,11 +249,9 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
- assertEquals(INVALID_TYPE, mHandler.mLastMessageType);
}
+ @Test
public void testUpdateStats_belowThreshold_doesNotNotify() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -276,12 +283,10 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
- mCv.block(WAIT_TIMEOUT);
- assertEquals(INVALID_TYPE, mHandler.mLastMessageType);
}
+
+ @Test
public void testUpdateStats_deviceAccess_notifies() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -314,11 +319,10 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
}
+ @Test
public void testUpdateStats_defaultAccess_notifiesSameUid() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -352,11 +356,10 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
}
+ @Test
public void testUpdateStats_defaultAccess_usageOtherUid_doesNotNotify() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -390,11 +393,9 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
- assertEquals(INVALID_TYPE, mHandler.mLastMessageType);
}
+ @Test
public void testUpdateStats_userAccess_usageSameUser_notifies() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -428,11 +429,10 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
}
+ @Test
public void testUpdateStats_userAccess_usageAnotherUser_doesNotNotify() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
@@ -467,14 +467,22 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
- assertEquals(INVALID_TYPE, mHandler.mLastMessageType);
}
private void waitForObserverToIdle() {
- // Send dummy message to make sure that any previous message has been handled
- mHandler.sendMessage(mHandler.obtainMessage(-1));
- mObserverHandlerThread.waitForIdle(WAIT_TIMEOUT);
+ waitForIdleLooper(mObserverHandlerThread.getLooper(), WAIT_TIMEOUT_MS);
+ waitForIdleLooper(mHandler.getLooper(), WAIT_TIMEOUT_MS);
}
+
+ // TODO: unify with ConnectivityService.waitForIdleHandler and
+ // NetworkServiceStatsTest.IdleableHandlerThread
+ private static void waitForIdleLooper(Looper looper, long timeoutMs) {
+ final ConditionVariable cv = new ConditionVariable();
+ final Handler handler = new Handler(looper);
+ handler.post(() -> cv.open());
+ if (!cv.block(timeoutMs)) {
+ fail("Looper did not become idle after " + timeoutMs + " ms");
+ }
+ }
+
}