Merge "HIDL: C++ Java parity"
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/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c96d19d..9e8acd0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1466,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.
@@ -1814,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) {
@@ -1873,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) {
@@ -2773,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;
}
}
@@ -2859,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() {
@@ -2890,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 {
@@ -3042,14 +3008,11 @@
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
int timeoutMs) {
- if (timeoutMs <= 0) {
- throw new IllegalArgumentException("Non-positive timeoutMs: " + 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.
@@ -3079,9 +3042,7 @@
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
Handler handler, int timeoutMs) {
- if (timeoutMs <= 0) {
- throw new IllegalArgumentException("Non-positive timeoutMs");
- }
+ checkTimeout(timeoutMs);
int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
CallbackHandler cbHandler = new CallbackHandler(handler);
requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler);
@@ -3153,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) {
@@ -3176,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) {
@@ -3184,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.");
}
/**
@@ -3257,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) {
@@ -3301,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);
}
/**
@@ -3339,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.
@@ -3375,6 +3343,7 @@
* Cannot be null.
*/
public void unregisterNetworkCallback(PendingIntent operation) {
+ checkPendingIntentNotNull(operation);
releaseNetworkRequest(operation);
}
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 7b845be..bccaf60 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -30,7 +30,6 @@
import java.util.Collections;
import java.util.Map;
-
/**
* A class representing service information for network service discovery
* {@see NsdManager}
@@ -43,7 +42,7 @@
private String mServiceType;
- private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<String, byte[]>();
+ private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<>();
private InetAddress mHost;
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 37d6757..2b03ed6 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -16,25 +16,17 @@
package android.util;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
import android.os.SystemClock;
-import android.text.format.DateUtils;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
-import java.util.TimeZone;
-
+import java.util.List;
+import libcore.util.TimeZoneFinder;
import libcore.util.ZoneInfoDB;
/**
@@ -45,14 +37,9 @@
private static final boolean DBG = false;
private static final String TAG = "TimeUtils";
- /** Cached results of getTineZones */
- private static final Object sLastLockObj = new Object();
- private static ArrayList<TimeZone> sLastZones = null;
- private static String sLastCountry = null;
-
/** Cached results of getTimeZonesWithUniqueOffsets */
private static final Object sLastUniqueLockObj = new Object();
- private static ArrayList<TimeZone> sLastUniqueZoneOffsets = null;
+ private static List<String> sLastUniqueZoneOffsets = null;
private static String sLastUniqueCountry = null;
/** {@hide} */
@@ -63,50 +50,39 @@
* and DST value at the specified moment in the specified country.
* Returns null if no suitable zone could be found.
*/
- public static TimeZone getTimeZone(int offset, boolean dst, long when, String country) {
- TimeZone best = null;
- final Date d = new Date(when);
+ public static java.util.TimeZone getTimeZone(
+ int offset, boolean dst, long when, String country) {
- TimeZone current = TimeZone.getDefault();
- String currentName = current.getID();
- int currentOffset = current.getOffset(when);
- boolean currentDst = current.inDaylightTime(d);
-
- for (TimeZone tz : getTimeZones(country)) {
- // If the current time zone is from the right country
- // and meets the other known properties, keep it
- // instead of changing to another one.
-
- if (tz.getID().equals(currentName)) {
- if (currentOffset == offset && currentDst == dst) {
- return current;
- }
- }
-
- // Otherwise, take the first zone from the right
- // country that has the correct current offset and DST.
- // (Keep iterating instead of returning in case we
- // haven't encountered the current time zone yet.)
-
- if (best == null) {
- if (tz.getOffset(when) == offset &&
- tz.inDaylightTime(d) == dst) {
- best = tz;
- }
- }
- }
-
- return best;
+ android.icu.util.TimeZone icuTimeZone = getIcuTimeZone(offset, dst, when, country);
+ // We must expose a java.util.TimeZone here for API compatibility because this is a public
+ // API method.
+ return icuTimeZone != null ? java.util.TimeZone.getTimeZone(icuTimeZone.getID()) : null;
}
/**
- * Return list of unique time zones for the country. Do not modify
+ * Tries to return a frozen ICU time zone that would have had the specified offset
+ * and DST value at the specified moment in the specified country.
+ * Returns null if no suitable zone could be found.
+ */
+ private static android.icu.util.TimeZone getIcuTimeZone(
+ int offset, boolean dst, long when, String country) {
+ if (country == null) {
+ return null;
+ }
+
+ android.icu.util.TimeZone bias = android.icu.util.TimeZone.getDefault();
+ return TimeZoneFinder.getInstance()
+ .lookupTimeZoneByCountryAndOffset(country, offset, dst, when, bias);
+ }
+
+ /**
+ * Returns an immutable list of unique time zone IDs for the country.
*
* @param country to find
- * @return list of unique time zones, maybe empty but never null. Do not modify.
+ * @return unmodifiable list of unique time zones, maybe empty but never null.
* @hide
*/
- public static ArrayList<TimeZone> getTimeZonesWithUniqueOffsets(String country) {
+ public static List<String> getTimeZoneIdsWithUniqueOffsets(String country) {
synchronized(sLastUniqueLockObj) {
if ((country != null) && country.equals(sLastUniqueCountry)) {
if (DBG) {
@@ -117,9 +93,9 @@
}
}
- Collection<TimeZone> zones = getTimeZones(country);
- ArrayList<TimeZone> uniqueTimeZones = new ArrayList<TimeZone>();
- for (TimeZone zone : zones) {
+ Collection<android.icu.util.TimeZone> zones = getIcuTimeZones(country);
+ ArrayList<android.icu.util.TimeZone> uniqueTimeZones = new ArrayList<>();
+ for (android.icu.util.TimeZone zone : zones) {
// See if we already have this offset,
// Using slow but space efficient and these are small.
boolean found = false;
@@ -129,7 +105,7 @@
break;
}
}
- if (found == false) {
+ if (!found) {
if (DBG) {
Log.d(TAG, "getTimeZonesWithUniqueOffsets: add unique offset=" +
zone.getRawOffset() + " zone.getID=" + zone.getID());
@@ -140,81 +116,43 @@
synchronized(sLastUniqueLockObj) {
// Cache the last result
- sLastUniqueZoneOffsets = uniqueTimeZones;
+ sLastUniqueZoneOffsets = extractZoneIds(uniqueTimeZones);
sLastUniqueCountry = country;
return sLastUniqueZoneOffsets;
}
}
+ private static List<String> extractZoneIds(List<android.icu.util.TimeZone> timeZones) {
+ List<String> ids = new ArrayList<>(timeZones.size());
+ for (android.icu.util.TimeZone timeZone : timeZones) {
+ ids.add(timeZone.getID());
+ }
+ return Collections.unmodifiableList(ids);
+ }
+
/**
- * Returns the time zones for the country, which is the code
- * attribute of the timezone element in time_zones_by_country.xml. Do not modify.
+ * Returns an immutable list of frozen ICU time zones for the country.
*
- * @param country is a two character country code.
- * @return TimeZone list, maybe empty but never null. Do not modify.
+ * @param countryIso is a two character country code.
+ * @return TimeZone list, maybe empty but never null.
* @hide
*/
- public static ArrayList<TimeZone> getTimeZones(String country) {
- synchronized (sLastLockObj) {
- if ((country != null) && country.equals(sLastCountry)) {
- if (DBG) Log.d(TAG, "getTimeZones(" + country + "): return cached version");
- return sLastZones;
+ private static List<android.icu.util.TimeZone> getIcuTimeZones(String countryIso) {
+ if (countryIso == null) {
+ if (DBG) Log.d(TAG, "getIcuTimeZones(null): return empty list");
+ return Collections.emptyList();
+ }
+ List<android.icu.util.TimeZone> timeZones =
+ TimeZoneFinder.getInstance().lookupTimeZonesByCountry(countryIso);
+ if (timeZones == null) {
+ if (DBG) {
+ Log.d(TAG, "getIcuTimeZones(" + countryIso
+ + "): returned null, converting to empty list");
}
+ return Collections.emptyList();
}
-
- ArrayList<TimeZone> tzs = new ArrayList<TimeZone>();
-
- if (country == null) {
- if (DBG) Log.d(TAG, "getTimeZones(null): return empty list");
- return tzs;
- }
-
- Resources r = Resources.getSystem();
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.time_zones_by_country);
-
- try {
- XmlUtils.beginDocument(parser, "timezones");
-
- while (true) {
- XmlUtils.nextElement(parser);
-
- String element = parser.getName();
- if (element == null || !(element.equals("timezone"))) {
- break;
- }
-
- String code = parser.getAttributeValue(null, "code");
-
- if (country.equals(code)) {
- if (parser.next() == XmlPullParser.TEXT) {
- String zoneIdString = parser.getText();
- TimeZone tz = TimeZone.getTimeZone(zoneIdString);
- if (tz.getID().startsWith("GMT") == false) {
- // tz.getID doesn't start not "GMT" so its valid
- tzs.add(tz);
- if (DBG) {
- Log.d(TAG, "getTimeZone('" + country + "'): found tz.getID=="
- + ((tz != null) ? tz.getID() : "<no tz>"));
- }
- }
- }
- }
- }
- } catch (XmlPullParserException e) {
- Log.e(TAG, "Got xml parser exception getTimeZone('" + country + "'): e=", e);
- } catch (IOException e) {
- Log.e(TAG, "Got IO exception getTimeZone('" + country + "'): e=", e);
- } finally {
- parser.close();
- }
-
- synchronized(sLastLockObj) {
- // Cache the last result;
- sLastZones = tzs;
- sLastCountry = country;
- return sLastZones;
- }
+ return timeZones;
}
/**
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f3ce719..270a215 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1433,7 +1433,6 @@
<java-symbol type="xml" name="password_kbd_symbols" />
<java-symbol type="xml" name="password_kbd_symbols_shift" />
<java-symbol type="xml" name="power_profile" />
- <java-symbol type="xml" name="time_zones_by_country" />
<java-symbol type="xml" name="sms_short_codes" />
<java-symbol type="xml" name="audio_assets" />
<java-symbol type="xml" name="global_keys" />
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
deleted file mode 100644
index 22bfea1..0000000
--- a/core/res/res/xml/time_zones_by_country.xml
+++ /dev/null
@@ -1,1372 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<timezones>
- <!-- ANDORRA, 1:00 -->
-
- <timezone code="ad">Europe/Andorra</timezone>
-
- <!-- UNITED ARAB EMIRATES, 4:00 -->
-
- <timezone code="ae">Asia/Dubai</timezone>
-
- <!-- AFGHANISTAN, 4:30 -->
-
- <timezone code="af">Asia/Kabul</timezone>
-
- <!-- ANTIGUA AND BARBUDA, -4:00 -->
-
- <timezone code="ag">America/Antigua</timezone>
-
- <!-- ANGUILLA, -4:00 -->
-
- <timezone code="ai">America/Anguilla</timezone>
-
- <!-- ALBANIA, 1:00 -->
-
- <timezone code="al">Europe/Tirane</timezone>
-
- <!-- ARMENIA, 4:00 -->
-
- <timezone code="am">Asia/Yerevan</timezone>
-
- <!-- ANGOLA, 1:00 -->
-
- <timezone code="ao">Africa/Luanda</timezone>
-
- <!-- ANTARCTICA, 12:00 -->
-
- <timezone code="aq">Antarctica/McMurdo</timezone>
-
- <!-- ANTARCTICA, 10:00 -->
-
- <timezone code="aq">Antarctica/DumontDUrville</timezone>
-
- <!-- ANTARCTICA, 8:00 -->
-
- <timezone code="aq">Antarctica/Casey</timezone>
-
- <!-- ANTARCTICA, 7:00 -->
-
- <timezone code="aq">Antarctica/Davis</timezone>
-
- <!-- ANTARCTICA, 5:00 -->
-
- <timezone code="aq">Antarctica/Mawson</timezone>
-
- <!-- ANTARCTICA, 6:00 -->
-
- <timezone code="aq">Antarctica/Vostok</timezone>
-
- <!-- ANTARCTICA, 3:00 -->
-
- <timezone code="aq">Antarctica/Syowa</timezone>
-
- <!-- ANTARCTICA, 0:00 -->
-
- <timezone code="aq">Antarctica/Troll</timezone>
-
- <!-- ANTARCTICA, -3:00 -->
-
- <timezone code="aq">Antarctica/Rothera</timezone>
-
- <!-- ANTARCTICA, -4:00 -->
-
- <timezone code="aq">Antarctica/Palmer</timezone>
-
- <!-- ARGENTINA, -3:00 -->
-
- <timezone code="ar">America/Argentina/Buenos_Aires</timezone>
- <timezone code="ar">America/Argentina/Cordoba</timezone>
- <timezone code="ar">America/Argentina/Salta</timezone>
- <timezone code="ar">America/Argentina/Jujuy</timezone>
- <timezone code="ar">America/Argentina/Tucuman</timezone>
- <timezone code="ar">America/Argentina/Catamarca</timezone>
- <timezone code="ar">America/Argentina/La_Rioja</timezone>
- <timezone code="ar">America/Argentina/San_Juan</timezone>
- <timezone code="ar">America/Argentina/Mendoza</timezone>
- <timezone code="ar">America/Argentina/San_Luis</timezone>
- <timezone code="ar">America/Argentina/Rio_Gallegos</timezone>
- <timezone code="ar">America/Argentina/Ushuaia</timezone>
-
- <!-- AMERICAN SAMOA, -11:00 -->
-
- <timezone code="as">Pacific/Pago_Pago</timezone>
-
- <!-- AUSTRIA, 1:00 -->
-
- <timezone code="at">Europe/Vienna</timezone>
-
- <!-- AUSTRALIA, 10:00 -->
-
- <timezone code="au">Australia/Sydney</timezone>
- <timezone code="au">Australia/Melbourne</timezone>
- <timezone code="au">Australia/Brisbane</timezone>
- <timezone code="au">Australia/Hobart</timezone>
- <timezone code="au">Australia/Currie</timezone>
- <timezone code="au">Australia/Lindeman</timezone>
-
- <!-- AUSTRALIA, 11:00 -->
- <timezone code="au">Antarctica/Macquarie</timezone>
-
- <!-- AUSTRALIA, 10:30 -->
-
- <timezone code="au">Australia/Lord_Howe</timezone>
-
- <!-- AUSTRALIA, 9:30 -->
-
- <timezone code="au">Australia/Adelaide</timezone>
- <timezone code="au">Australia/Broken_Hill</timezone>
- <timezone code="au">Australia/Darwin</timezone>
-
- <!-- AUSTRALIA, 8:00 -->
-
- <timezone code="au">Australia/Perth</timezone>
-
- <!-- AUSTRALIA, 8:45 -->
-
- <timezone code="au">Australia/Eucla</timezone>
-
- <!-- ARUBA, -4:00 -->
-
- <timezone code="aw">America/Aruba</timezone>
-
- <!-- ALAND ISLANDS, 2:00 -->
-
- <timezone code="ax">Europe/Mariehamn</timezone>
-
- <!-- AZERBAIJAN, 4:00 -->
-
- <timezone code="az">Asia/Baku</timezone>
-
- <!-- BOSNIA AND HERZEGOVINA, 1:00 -->
-
- <timezone code="ba">Europe/Sarajevo</timezone>
-
- <!-- BARBADOS, -4:00 -->
-
- <timezone code="bb">America/Barbados</timezone>
-
- <!-- BANGLADESH, 6:00 -->
-
- <timezone code="bd">Asia/Dhaka</timezone>
-
- <!-- BELGIUM, 1:00 -->
-
- <timezone code="be">Europe/Brussels</timezone>
-
- <!-- BURKINA FASO, 0:00 -->
-
- <timezone code="bf">Africa/Ouagadougou</timezone>
-
- <!-- BULGARIA, 2:00 -->
-
- <timezone code="bg">Europe/Sofia</timezone>
-
- <!-- BAHRAIN, 3:00 -->
-
- <timezone code="bh">Asia/Bahrain</timezone>
-
- <!-- BURUNDI, 2:00 -->
-
- <timezone code="bi">Africa/Bujumbura</timezone>
-
- <!-- BENIN, 1:00 -->
-
- <timezone code="bj">Africa/Porto-Novo</timezone>
-
- <!-- Saint Barthélemy, -4:00 -->
-
- <timezone code="bl">America/St_Barthelemy</timezone>
-
- <!-- BERMUDA, -4:00 -->
-
- <timezone code="bm">Atlantic/Bermuda</timezone>
-
- <!-- BRUNEI DARUSSALAM, 8:00 -->
-
- <timezone code="bn">Asia/Brunei</timezone>
-
- <!-- BOLIVIA, -4:00 -->
-
- <timezone code="bo">America/La_Paz</timezone>
-
- <!-- Caribbean Netherlands, -4:00 -->
-
- <timezone code="bq">America/Kralendijk</timezone>
-
- <!-- BRAZIL, -2:00 -->
-
- <timezone code="br">America/Noronha</timezone>
-
- <!-- BRAZIL, -3:00 -->
-
- <timezone code="br">America/Sao_Paulo</timezone>
- <timezone code="br">America/Belem</timezone>
- <timezone code="br">America/Fortaleza</timezone>
- <timezone code="br">America/Recife</timezone>
- <timezone code="br">America/Araguaina</timezone>
- <timezone code="br">America/Maceio</timezone>
- <timezone code="br">America/Bahia</timezone>
- <timezone code="br">America/Santarem</timezone>
-
- <!-- BRAZIL, -4:00 -->
-
- <timezone code="br">America/Manaus</timezone>
- <timezone code="br">America/Campo_Grande</timezone>
- <timezone code="br">America/Cuiaba</timezone>
- <timezone code="br">America/Porto_Velho</timezone>
- <timezone code="br">America/Boa_Vista</timezone>
-
- <!-- BRAZIL, -5:00 -->
-
- <timezone code="br">America/Eirunepe</timezone>
- <timezone code="br">America/Rio_Branco</timezone>
-
- <!-- BAHAMAS, -5:00 -->
-
- <timezone code="bs">America/Nassau</timezone>
-
- <!-- BHUTAN, 6:00 -->
-
- <timezone code="bt">Asia/Thimphu</timezone>
-
- <!-- BOTSWANA, 2:00 -->
-
- <timezone code="bw">Africa/Gaborone</timezone>
-
- <!-- BELARUS, 3:00 -->
-
- <timezone code="by">Europe/Minsk</timezone>
-
- <!-- BELIZE, -6:00 -->
-
- <timezone code="bz">America/Belize</timezone>
-
- <!-- CANADA, -3:30 -->
-
- <timezone code="ca">America/St_Johns</timezone>
-
- <!-- CANADA, -4:00 -->
-
- <timezone code="ca">America/Halifax</timezone>
- <timezone code="ca">America/Glace_Bay</timezone>
- <timezone code="ca">America/Moncton</timezone>
- <timezone code="ca">America/Goose_Bay</timezone>
- <timezone code="ca">America/Blanc-Sablon</timezone>
-
- <!-- CANADA, -5:00 -->
-
- <timezone code="ca">America/Toronto</timezone>
- <timezone code="ca">America/Nipigon</timezone>
- <timezone code="ca">America/Thunder_Bay</timezone>
- <timezone code="ca">America/Iqaluit</timezone>
- <timezone code="ca">America/Pangnirtung</timezone>
- <timezone code="ca">America/Atikokan</timezone>
-
- <!-- CANADA, -6:00 -->
-
- <timezone code="ca">America/Winnipeg</timezone>
- <timezone code="ca">America/Regina</timezone>
- <timezone code="ca">America/Rankin_Inlet</timezone>
- <timezone code="ca">America/Rainy_River</timezone>
- <timezone code="ca">America/Swift_Current</timezone>
- <timezone code="ca">America/Resolute</timezone>
-
- <!-- CANADA, -7:00 -->
-
- <timezone code="ca">America/Edmonton</timezone>
- <timezone code="ca">America/Cambridge_Bay</timezone>
- <timezone code="ca">America/Yellowknife</timezone>
- <timezone code="ca">America/Inuvik</timezone>
- <timezone code="ca">America/Dawson_Creek</timezone>
- <timezone code="ca">America/Creston</timezone>
- <timezone code="ca">America/Fort_Nelson</timezone>
-
- <!-- CANADA, -8:00 -->
-
- <timezone code="ca">America/Vancouver</timezone>
- <timezone code="ca">America/Whitehorse</timezone>
- <timezone code="ca">America/Dawson</timezone>
-
- <!-- COCOS (KEELING) ISLANDS, 6:30 -->
-
- <timezone code="cc">Indian/Cocos</timezone>
-
- <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 2:00 -->
-
- <timezone code="cd">Africa/Lubumbashi</timezone>
-
- <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 1:00 -->
-
- <timezone code="cd">Africa/Kinshasa</timezone>
-
- <!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
-
- <timezone code="cf">Africa/Bangui</timezone>
-
- <!-- CONGO, 1:00 -->
-
- <timezone code="cg">Africa/Brazzaville</timezone>
-
- <!-- SWITZERLAND, 1:00 -->
-
- <timezone code="ch">Europe/Zurich</timezone>
-
- <!-- COTE D'IVOIRE, 0:00 -->
-
- <timezone code="ci">Africa/Abidjan</timezone>
-
- <!-- COOK ISLANDS, -10:00 -->
-
- <timezone code="ck">Pacific/Rarotonga</timezone>
-
- <!-- CHILE, -3:00 -->
-
- <timezone code="cl">America/Punta_Arenas</timezone>
-
- <!-- CHILE, -4:00 -->
-
- <timezone code="cl">America/Santiago</timezone>
-
- <!-- CHILE, -6:00 -->
-
- <timezone code="cl">Pacific/Easter</timezone>
-
- <!-- CAMEROON, 1:00 -->
-
- <timezone code="cm">Africa/Douala</timezone>
-
- <!-- CHINA, 8:00 -->
-
- <timezone code="cn">Asia/Shanghai</timezone>
-
- <!-- CHINA, 6:00 -->
-
- <timezone code="cn">Asia/Urumqi</timezone>
-
- <!-- COLOMBIA, -5:00 -->
-
- <timezone code="co">America/Bogota</timezone>
-
- <!-- COSTA RICA, -6:00 -->
-
- <timezone code="cr">America/Costa_Rica</timezone>
-
- <!-- CUBA, -5:00 -->
-
- <timezone code="cu">America/Havana</timezone>
-
- <!-- CAPE VERDE, -1:00 -->
-
- <timezone code="cv">Atlantic/Cape_Verde</timezone>
-
- <!-- Curaçao, -4:00 -->
-
- <timezone code="cw">America/Curacao</timezone>
-
- <!-- CHRISTMAS ISLAND, 7:00 -->
-
- <timezone code="cx">Indian/Christmas</timezone>
-
- <!-- CYPRUS, 2:00 -->
-
- <timezone code="cy">Asia/Nicosia</timezone>
-
- <!-- CYPRUS, 3:00 -->
-
- <timezone code="cy">Asia/Famagusta</timezone>
-
- <!-- CZECH REPUBLIC, 1:00 -->
-
- <timezone code="cz">Europe/Prague</timezone>
-
- <!-- GERMANY, 1:00 -->
-
- <timezone code="de">Europe/Berlin</timezone>
- <timezone code="de">Europe/Busingen</timezone>
-
- <!-- DJIBOUTI, 3:00 -->
-
- <timezone code="dj">Africa/Djibouti</timezone>
-
- <!-- DENMARK, 1:00 -->
-
- <timezone code="dk">Europe/Copenhagen</timezone>
-
- <!-- DOMINICA, -4:00 -->
-
- <timezone code="dm">America/Dominica</timezone>
-
- <!-- DOMINICAN REPUBLIC, -4:00 -->
-
- <timezone code="do">America/Santo_Domingo</timezone>
-
- <!-- ALGERIA, 1:00 -->
-
- <timezone code="dz">Africa/Algiers</timezone>
-
- <!-- ECUADOR, -5:00 -->
-
- <timezone code="ec">America/Guayaquil</timezone>
-
- <!-- ECUADOR, -6:00 -->
-
- <timezone code="ec">Pacific/Galapagos</timezone>
-
- <!-- ESTONIA, 2:00 -->
-
- <timezone code="ee">Europe/Tallinn</timezone>
-
- <!-- EGYPT, 2:00 -->
-
- <timezone code="eg">Africa/Cairo</timezone>
-
- <!-- WESTERN SAHARA, 0:00 -->
-
- <timezone code="eh">Africa/El_Aaiun</timezone>
-
- <!-- ERITREA, 3:00 -->
-
- <timezone code="er">Africa/Asmara</timezone>
-
- <!-- SPAIN, 1:00 -->
-
- <timezone code="es">Europe/Madrid</timezone>
- <timezone code="es">Africa/Ceuta</timezone>
-
- <!-- SPAIN, 0:00 -->
-
- <timezone code="es">Atlantic/Canary</timezone>
-
- <!-- ETHIOPIA, 3:00 -->
-
- <timezone code="et">Africa/Addis_Ababa</timezone>
-
- <!-- FINLAND, 2:00 -->
-
- <timezone code="fi">Europe/Helsinki</timezone>
-
- <!-- FIJI, 12:00 -->
-
- <timezone code="fj">Pacific/Fiji</timezone>
-
- <!-- FALKLAND ISLANDS (MALVINAS), -3:00 -->
-
- <timezone code="fk">Atlantic/Stanley</timezone>
-
- <!-- MICRONESIA, FEDERATED STATES OF, 11:00 -->
-
- <timezone code="fm">Pacific/Pohnpei</timezone>
- <timezone code="fm">Pacific/Kosrae</timezone>
-
- <!-- MICRONESIA, FEDERATED STATES OF, 10:00 -->
-
- <timezone code="fm">Pacific/Chuuk</timezone>
-
- <!-- FAROE ISLANDS, 0:00 -->
-
- <timezone code="fo">Atlantic/Faroe</timezone>
-
- <!-- FRANCE, 1:00 -->
-
- <timezone code="fr">Europe/Paris</timezone>
-
- <!-- GABON, 1:00 -->
-
- <timezone code="ga">Africa/Libreville</timezone>
-
- <!-- UNITED KINGDOM, 0:00 -->
-
- <timezone code="gb">Europe/London</timezone>
-
- <!-- GRENADA, -4:00 -->
-
- <timezone code="gd">America/Grenada</timezone>
-
- <!-- GEORGIA, 4:00 -->
-
- <timezone code="ge">Asia/Tbilisi</timezone>
-
- <!-- FRENCH GUIANA, -3:00 -->
-
- <timezone code="gf">America/Cayenne</timezone>
-
- <!-- GUERNSEY, 0:00 -->
-
- <timezone code="gg">Europe/Guernsey</timezone>
-
- <!-- GHANA, 0:00 -->
-
- <timezone code="gh">Africa/Accra</timezone>
-
- <!-- GIBRALTAR, 1:00 -->
-
- <timezone code="gi">Europe/Gibraltar</timezone>
-
- <!-- GREENLAND, 0:00 -->
-
- <timezone code="gl">America/Danmarkshavn</timezone>
-
- <!-- GREENLAND, -1:00 -->
-
- <timezone code="gl">America/Scoresbysund</timezone>
-
- <!-- GREENLAND, -3:00 -->
-
- <timezone code="gl">America/Godthab</timezone>
-
- <!-- GREENLAND, -4:00 -->
-
- <timezone code="gl">America/Thule</timezone>
-
- <!-- GAMBIA, 0:00 -->
-
- <timezone code="gm">Africa/Banjul</timezone>
-
- <!-- GUINEA, 0:00 -->
-
- <timezone code="gn">Africa/Conakry</timezone>
-
- <!-- GUADELOUPE, -4:00 -->
-
- <timezone code="gp">America/Guadeloupe</timezone>
-
- <!-- EQUATORIAL GUINEA, 1:00 -->
-
- <timezone code="gq">Africa/Malabo</timezone>
-
- <!-- GREECE, 2:00 -->
-
- <timezone code="gr">Europe/Athens</timezone>
-
- <!-- SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS, -2:00 -->
-
- <timezone code="gs">Atlantic/South_Georgia</timezone>
-
- <!-- GUATEMALA, -6:00 -->
-
- <timezone code="gt">America/Guatemala</timezone>
-
- <!-- GUAM, 10:00 -->
-
- <timezone code="gu">Pacific/Guam</timezone>
-
- <!-- GUINEA-BISSAU, 0:00 -->
-
- <timezone code="gw">Africa/Bissau</timezone>
-
- <!-- GUYANA, -4:00 -->
-
- <timezone code="gy">America/Guyana</timezone>
-
- <!-- HONG KONG, 8:00 -->
-
- <timezone code="hk">Asia/Hong_Kong</timezone>
-
- <!-- HONDURAS, -6:00 -->
-
- <timezone code="hn">America/Tegucigalpa</timezone>
-
- <!-- CROATIA, 1:00 -->
-
- <timezone code="hr">Europe/Zagreb</timezone>
-
- <!-- HAITI, -5:00 -->
-
- <timezone code="ht">America/Port-au-Prince</timezone>
-
- <!-- HUNGARY, 1:00 -->
-
- <timezone code="hu">Europe/Budapest</timezone>
-
- <!-- INDONESIA, 9:00 -->
-
- <timezone code="id">Asia/Jayapura</timezone>
-
- <!-- INDONESIA, 8:00 -->
-
- <timezone code="id">Asia/Makassar</timezone>
-
- <!-- INDONESIA, 7:00 -->
-
- <timezone code="id">Asia/Jakarta</timezone>
- <timezone code="id">Asia/Pontianak</timezone>
-
- <!-- IRELAND, 0:00 -->
-
- <timezone code="ie">Europe/Dublin</timezone>
-
- <!-- ISRAEL, 2:00 -->
-
- <timezone code="il">Asia/Jerusalem</timezone>
-
- <!-- ISLE OF MAN, 0:00 -->
-
- <timezone code="im">Europe/Isle_of_Man</timezone>
-
- <!-- INDIA, 5:30 -->
-
- <timezone code="in">Asia/Kolkata</timezone>
-
- <!-- BRITISH INDIAN OCEAN TERRITORY, 6:00 -->
-
- <timezone code="io">Indian/Chagos</timezone>
-
- <!-- IRAQ, 3:00 -->
-
- <timezone code="iq">Asia/Baghdad</timezone>
-
- <!-- IRAN, ISLAMIC REPUBLIC OF, 3:30 -->
-
- <timezone code="ir">Asia/Tehran</timezone>
-
- <!-- ICELAND, 0:00 -->
-
- <timezone code="is">Atlantic/Reykjavik</timezone>
-
- <!-- ITALY, 1:00 -->
-
- <timezone code="it">Europe/Rome</timezone>
-
- <!-- JERSEY, 0:00 -->
-
- <timezone code="je">Europe/Jersey</timezone>
-
- <!-- JAMAICA, -5:00 -->
-
- <timezone code="jm">America/Jamaica</timezone>
-
- <!-- JORDAN, 2:00 -->
-
- <timezone code="jo">Asia/Amman</timezone>
-
- <!-- JAPAN, 9:00 -->
-
- <timezone code="jp">Asia/Tokyo</timezone>
-
- <!-- KENYA, 3:00 -->
-
- <timezone code="ke">Africa/Nairobi</timezone>
-
- <!-- KYRGYZSTAN, 6:00 -->
-
- <timezone code="kg">Asia/Bishkek</timezone>
-
- <!-- CAMBODIA, 7:00 -->
-
- <timezone code="kh">Asia/Phnom_Penh</timezone>
-
- <!-- KIRIBATI, 14:00 -->
-
- <timezone code="ki">Pacific/Kiritimati</timezone>
-
- <!-- KIRIBATI, 13:00 -->
-
- <timezone code="ki">Pacific/Enderbury</timezone>
-
- <!-- KIRIBATI, 12:00 -->
-
- <timezone code="ki">Pacific/Tarawa</timezone>
-
- <!-- COMOROS, 3:00 -->
-
- <timezone code="km">Indian/Comoro</timezone>
-
- <!-- SAINT KITTS AND NEVIS, -4:00 -->
-
- <timezone code="kn">America/St_Kitts</timezone>
-
- <!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
-
- <timezone code="kp">Asia/Pyongyang</timezone>
-
- <!-- KOREA, REPUBLIC OF, 9:00 -->
-
- <timezone code="kr">Asia/Seoul</timezone>
-
- <!-- KUWAIT, 3:00 -->
-
- <timezone code="kw">Asia/Kuwait</timezone>
-
- <!-- CAYMAN ISLANDS, -5:00 -->
-
- <timezone code="ky">America/Cayman</timezone>
-
- <!-- KAZAKHSTAN, 6:00 -->
-
- <timezone code="kz">Asia/Almaty</timezone>
- <timezone code="kz">Asia/Qyzylorda</timezone>
-
- <!-- KAZAKHSTAN, 5:00 -->
-
- <timezone code="kz">Asia/Aqtau</timezone>
- <timezone code="kz">Asia/Oral</timezone>
- <timezone code="kz">Asia/Aqtobe</timezone>
- <timezone code="kz">Asia/Atyrau</timezone>
-
- <!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
-
- <timezone code="la">Asia/Vientiane</timezone>
-
- <!-- LEBANON, 2:00 -->
-
- <timezone code="lb">Asia/Beirut</timezone>
-
- <!-- SAINT LUCIA, -4:00 -->
-
- <timezone code="lc">America/St_Lucia</timezone>
-
- <!-- LIECHTENSTEIN, 1:00 -->
-
- <timezone code="li">Europe/Vaduz</timezone>
-
- <!-- SRI LANKA, 5:30 -->
-
- <timezone code="lk">Asia/Colombo</timezone>
-
- <!-- LIBERIA, 0:00 -->
-
- <timezone code="lr">Africa/Monrovia</timezone>
-
- <!-- LESOTHO, 2:00 -->
-
- <timezone code="ls">Africa/Maseru</timezone>
-
- <!-- LITHUANIA, 2:00 -->
-
- <timezone code="lt">Europe/Vilnius</timezone>
-
- <!-- LUXEMBOURG, 1:00 -->
-
- <timezone code="lu">Europe/Luxembourg</timezone>
-
- <!-- LATVIA, 2:00 -->
-
- <timezone code="lv">Europe/Riga</timezone>
-
- <!-- LIBYAN ARAB JAMAHIRIYA, 2:00 -->
-
- <timezone code="ly">Africa/Tripoli</timezone>
-
- <!-- MOROCCO, 0:00 -->
-
- <timezone code="ma">Africa/Casablanca</timezone>
-
- <!-- MONACO, 1:00 -->
-
- <timezone code="mc">Europe/Monaco</timezone>
-
- <!-- MOLDOVA, 2:00 -->
-
- <timezone code="md">Europe/Chisinau</timezone>
-
- <!-- MONTENEGRO, 1:00 -->
-
- <timezone code="me">Europe/Podgorica</timezone>
-
- <!-- Collectivity of Saint Martin, -4:00 -->
-
- <timezone code="mf">America/Marigot</timezone>
-
- <!-- MADAGASCAR, 3:00 -->
-
- <timezone code="mg">Indian/Antananarivo</timezone>
-
- <!-- MARSHALL ISLANDS, 12:00 -->
-
- <timezone code="mh">Pacific/Majuro</timezone>
- <timezone code="mh">Pacific/Kwajalein</timezone>
-
- <!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
-
- <timezone code="mk">Europe/Skopje</timezone>
-
- <!-- MALI, 0:00 -->
-
- <timezone code="ml">Africa/Bamako</timezone>
-
- <!-- MYANMAR, 6:30 -->
-
- <timezone code="mm">Asia/Yangon</timezone>
-
- <!-- MONGOLIA, 8:00 -->
-
- <timezone code="mn">Asia/Choibalsan</timezone>
- <timezone code="mn">Asia/Ulaanbaatar</timezone>
-
- <!-- MONGOLIA, 7:00 -->
-
- <timezone code="mn">Asia/Hovd</timezone>
-
- <!-- MACAO, 8:00 -->
-
- <timezone code="mo">Asia/Macau</timezone>
-
- <!-- NORTHERN MARIANA ISLANDS, 10:00 -->
-
- <timezone code="mp">Pacific/Saipan</timezone>
-
- <!-- MARTINIQUE, -4:00 -->
-
- <timezone code="mq">America/Martinique</timezone>
-
- <!-- MAURITANIA, 0:00 -->
-
- <timezone code="mr">Africa/Nouakchott</timezone>
-
- <!-- MONTSERRAT, -4:00 -->
-
- <timezone code="ms">America/Montserrat</timezone>
-
- <!-- MALTA, 1:00 -->
-
- <timezone code="mt">Europe/Malta</timezone>
-
- <!-- MAURITIUS, 4:00 -->
-
- <timezone code="mu">Indian/Mauritius</timezone>
-
- <!-- MALDIVES, 5:00 -->
-
- <timezone code="mv">Indian/Maldives</timezone>
-
- <!-- MALAWI, 2:00 -->
-
- <timezone code="mw">Africa/Blantyre</timezone>
-
- <!-- MEXICO, -6:00 -->
-
- <timezone code="mx">America/Mexico_City</timezone>
- <timezone code="mx">America/Merida</timezone>
- <timezone code="mx">America/Monterrey</timezone>
- <timezone code="mx">America/Matamoros</timezone>
- <timezone code="mx">America/Bahia_Banderas</timezone>
-
- <!-- MEXICO, -5:00 -->
-
- <timezone code="mx">America/Cancun</timezone>
-
- <!-- MEXICO, -7:00 -->
-
- <timezone code="mx">America/Chihuahua</timezone>
- <timezone code="mx">America/Hermosillo</timezone>
- <timezone code="mx">America/Mazatlan</timezone>
- <timezone code="mx">America/Ojinaga</timezone>
-
- <!-- MEXICO, -8:00 -->
-
- <timezone code="mx">America/Tijuana</timezone>
-
- <!-- MALAYSIA, 8:00 -->
-
- <timezone code="my">Asia/Kuala_Lumpur</timezone>
- <timezone code="my">Asia/Kuching</timezone>
-
- <!-- MOZAMBIQUE, 2:00 -->
-
- <timezone code="mz">Africa/Maputo</timezone>
-
- <!-- NAMIBIA, 1:00 -->
-
- <timezone code="na">Africa/Windhoek</timezone>
-
- <!-- NEW CALEDONIA, 11:00 -->
-
- <timezone code="nc">Pacific/Noumea</timezone>
-
- <!-- NIGER, 1:00 -->
-
- <timezone code="ne">Africa/Niamey</timezone>
-
- <!-- NORFOLK ISLAND, 11:30 -->
-
- <timezone code="nf">Pacific/Norfolk</timezone>
-
- <!-- NIGERIA, 1:00 -->
-
- <timezone code="ng">Africa/Lagos</timezone>
-
- <!-- NICARAGUA, -6:00 -->
-
- <timezone code="ni">America/Managua</timezone>
-
- <!-- NETHERLANDS, 1:00 -->
-
- <timezone code="nl">Europe/Amsterdam</timezone>
-
- <!-- NORWAY, 1:00 -->
-
- <timezone code="no">Europe/Oslo</timezone>
-
- <!-- NEPAL, 5:45 -->
-
- <timezone code="np">Asia/Kathmandu</timezone>
-
- <!-- NAURU, 12:00 -->
-
- <timezone code="nr">Pacific/Nauru</timezone>
-
- <!-- NIUE, -11:00 -->
-
- <timezone code="nu">Pacific/Niue</timezone>
-
- <!-- NEW ZEALAND, 12:00 -->
-
- <timezone code="nz">Pacific/Auckland</timezone>
-
- <!-- NEW ZEALAND, 12:45 -->
-
- <timezone code="nz">Pacific/Chatham</timezone>
-
- <!-- OMAN, 4:00 -->
-
- <timezone code="om">Asia/Muscat</timezone>
-
- <!-- PANAMA, -5:00 -->
-
- <timezone code="pa">America/Panama</timezone>
-
- <!-- PERU, -5:00 -->
-
- <timezone code="pe">America/Lima</timezone>
-
- <!-- FRENCH POLYNESIA, -9:00 -->
-
- <timezone code="pf">Pacific/Gambier</timezone>
-
- <!-- FRENCH POLYNESIA, -9:30 -->
-
- <timezone code="pf">Pacific/Marquesas</timezone>
-
- <!-- FRENCH POLYNESIA, -10:00 -->
-
- <timezone code="pf">Pacific/Tahiti</timezone>
-
- <!-- PAPUA NEW GUINEA, 10:00 -->
-
- <timezone code="pg">Pacific/Port_Moresby</timezone>
-
- <!-- PAPUA NEW GUINEA, 11:00 -->
-
- <timezone code="pg">Pacific/Bougainville</timezone>
-
- <!-- PHILIPPINES, 8:00 -->
-
- <timezone code="ph">Asia/Manila</timezone>
-
- <!-- PAKISTAN, 5:00 -->
-
- <timezone code="pk">Asia/Karachi</timezone>
-
- <!-- POLAND, 1:00 -->
-
- <timezone code="pl">Europe/Warsaw</timezone>
-
- <!-- SAINT PIERRE AND MIQUELON, -3:00 -->
-
- <timezone code="pm">America/Miquelon</timezone>
-
- <!-- PITCAIRN, -8:00 -->
-
- <timezone code="pn">Pacific/Pitcairn</timezone>
-
- <!-- PUERTO RICO, -4:00 -->
-
- <timezone code="pr">America/Puerto_Rico</timezone>
-
- <!-- PALESTINE, 2:00 -->
-
- <timezone code="ps">Asia/Gaza</timezone>
- <timezone code="ps">Asia/Hebron</timezone>
-
- <!-- PORTUGAL, 0:00 -->
-
- <timezone code="pt">Europe/Lisbon</timezone>
- <timezone code="pt">Atlantic/Madeira</timezone>
-
- <!-- PORTUGAL, -1:00 -->
-
- <timezone code="pt">Atlantic/Azores</timezone>
-
- <!-- PALAU, 9:00 -->
-
- <timezone code="pw">Pacific/Palau</timezone>
-
- <!-- PARAGUAY, -4:00 -->
-
- <timezone code="py">America/Asuncion</timezone>
-
- <!-- QATAR, 3:00 -->
-
- <timezone code="qa">Asia/Qatar</timezone>
-
- <!-- REUNION, 4:00 -->
-
- <timezone code="re">Indian/Reunion</timezone>
-
- <!-- ROMANIA, 2:00 -->
-
- <timezone code="ro">Europe/Bucharest</timezone>
-
- <!-- SERBIA, 1:00 -->
-
- <timezone code="rs">Europe/Belgrade</timezone>
-
- <!-- RUSSIAN FEDERATION, 12:00 -->
-
- <timezone code="ru">Asia/Kamchatka</timezone>
- <timezone code="ru">Asia/Anadyr</timezone>
-
- <!-- RUSSIAN FEDERATION, 11:00 -->
-
- <timezone code="ru">Asia/Magadan</timezone>
- <timezone code="ru">Asia/Sakhalin</timezone>
- <timezone code="ru">Asia/Srednekolymsk</timezone>
-
- <!-- RUSSIAN FEDERATION, 10:00 -->
-
- <timezone code="ru">Asia/Vladivostok</timezone>
- <timezone code="ru">Asia/Ust-Nera</timezone>
-
- <!-- RUSSIAN FEDERATION, 9:00 -->
-
- <timezone code="ru">Asia/Yakutsk</timezone>
- <timezone code="ru">Asia/Chita</timezone>
- <timezone code="ru">Asia/Khandyga</timezone>
-
- <!-- RUSSIAN FEDERATION, 8:00 -->
-
- <timezone code="ru">Asia/Irkutsk</timezone>
-
- <!-- RUSSIAN FEDERATION, 7:00 -->
-
- <timezone code="ru">Asia/Krasnoyarsk</timezone>
- <timezone code="ru">Asia/Novosibirsk</timezone>
- <timezone code="ru">Asia/Barnaul</timezone>
- <timezone code="ru">Asia/Novokuznetsk</timezone>
- <timezone code="ru">Asia/Tomsk</timezone>
-
- <!-- RUSSIAN FEDERATION, 6:00 -->
-
- <timezone code="ru">Asia/Omsk</timezone>
-
- <!-- RUSSIAN FEDERATION, 5:00 -->
-
- <timezone code="ru">Asia/Yekaterinburg</timezone>
-
- <!-- RUSSIAN FEDERATION, 4:00 -->
-
- <timezone code="ru">Europe/Samara</timezone>
- <timezone code="ru">Europe/Astrakhan</timezone>
- <timezone code="ru">Europe/Ulyanovsk</timezone>
- <timezone code="ru">Europe/Saratov</timezone>
-
- <!-- RUSSIAN FEDERATION, 3:00 -->
-
- <timezone code="ru">Europe/Moscow</timezone>
- <timezone code="ru">Europe/Volgograd</timezone>
- <timezone code="ru">Europe/Kirov</timezone>
- <timezone code="ru">Europe/Simferopol</timezone>
-
- <!-- RUSSIAN FEDERATION, 2:00 -->
-
- <timezone code="ru">Europe/Kaliningrad</timezone>
-
- <!-- RWANDA, 2:00 -->
-
- <timezone code="rw">Africa/Kigali</timezone>
-
- <!-- SAUDI ARABIA, 3:00 -->
-
- <timezone code="sa">Asia/Riyadh</timezone>
-
- <!-- SOLOMON ISLANDS, 11:00 -->
-
- <timezone code="sb">Pacific/Guadalcanal</timezone>
-
- <!-- SEYCHELLES, 4:00 -->
-
- <timezone code="sc">Indian/Mahe</timezone>
-
- <!-- SUDAN, 3:00 -->
-
- <timezone code="sd">Africa/Khartoum</timezone>
-
- <!-- SWEDEN, 1:00 -->
-
- <timezone code="se">Europe/Stockholm</timezone>
-
- <!-- SINGAPORE, 8:00 -->
-
- <timezone code="sg">Asia/Singapore</timezone>
-
- <!-- SAINT HELENA, 0:00 -->
-
- <timezone code="sh">Atlantic/St_Helena</timezone>
-
- <!-- SLOVENIA, 1:00 -->
-
- <timezone code="si">Europe/Ljubljana</timezone>
-
- <!-- SVALBARD AND JAN MAYEN, 1:00 -->
-
- <timezone code="sj">Arctic/Longyearbyen</timezone>
-
- <!-- SLOVAKIA, 1:00 -->
-
- <timezone code="sk">Europe/Bratislava</timezone>
-
- <!-- SIERRA LEONE, 0:00 -->
-
- <timezone code="sl">Africa/Freetown</timezone>
-
- <!-- SAN MARINO, 1:00 -->
-
- <timezone code="sm">Europe/San_Marino</timezone>
-
- <!-- SENEGAL, 0:00 -->
-
- <timezone code="sn">Africa/Dakar</timezone>
-
- <!-- SOMALIA, 3:00 -->
-
- <timezone code="so">Africa/Mogadishu</timezone>
-
- <!-- SURINAME, -3:00 -->
-
- <timezone code="sr">America/Paramaribo</timezone>
-
- <!-- South Sudan, 3:00 -->
-
- <timezone code="ss">Africa/Juba</timezone>
-
- <!-- SAO TOME AND PRINCIPE, 0:00 -->
-
- <timezone code="st">Africa/Sao_Tome</timezone>
-
- <!-- EL SALVADOR, -6:00 -->
-
- <timezone code="sv">America/El_Salvador</timezone>
-
- <!-- Sint Maarten, -4:00 -->
-
- <timezone code="sx">America/Lower_Princes</timezone>
-
- <!-- SYRIAN ARAB REPUBLIC, 2:00 -->
-
- <timezone code="sy">Asia/Damascus</timezone>
-
- <!-- SWAZILAND, 2:00 -->
-
- <timezone code="sz">Africa/Mbabane</timezone>
-
- <!-- TURKS AND CAICOS ISLANDS, -4:00 -->
-
- <timezone code="tc">America/Grand_Turk</timezone>
-
- <!-- CHAD, 1:00 -->
-
- <timezone code="td">Africa/Ndjamena</timezone>
-
- <!-- FRENCH SOUTHERN TERRITORIES, 5:00 -->
-
- <timezone code="tf">Indian/Kerguelen</timezone>
-
- <!-- TOGO, 0:00 -->
-
- <timezone code="tg">Africa/Lome</timezone>
-
- <!-- THAILAND, 7:00 -->
-
- <timezone code="th">Asia/Bangkok</timezone>
-
- <!-- TAJIKISTAN, 5:00 -->
-
- <timezone code="tj">Asia/Dushanbe</timezone>
-
- <!-- TOKELAU, +13:00 -->
-
- <timezone code="tk">Pacific/Fakaofo</timezone>
-
- <!-- TIMOR-LESTE, 9:00 -->
-
- <timezone code="tl">Asia/Dili</timezone>
-
- <!-- TURKMENISTAN, 5:00 -->
-
- <timezone code="tm">Asia/Ashgabat</timezone>
-
- <!-- TUNISIA, 1:00 -->
-
- <timezone code="tn">Africa/Tunis</timezone>
-
- <!-- TONGA, 13:00 -->
-
- <timezone code="to">Pacific/Tongatapu</timezone>
-
- <!-- TURKEY, 3:00 -->
-
- <timezone code="tr">Europe/Istanbul</timezone>
-
- <!-- TRINIDAD AND TOBAGO, -4:00 -->
-
- <timezone code="tt">America/Port_of_Spain</timezone>
-
- <!-- TUVALU, 12:00 -->
-
- <timezone code="tv">Pacific/Funafuti</timezone>
-
- <!-- TAIWAN, PROVINCE OF CHINA, 8:00 -->
-
- <timezone code="tw">Asia/Taipei</timezone>
-
- <!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
-
- <timezone code="tz">Africa/Dar_es_Salaam</timezone>
-
- <!-- UKRAINE, 2:00 -->
-
- <timezone code="ua">Europe/Kiev</timezone>
- <timezone code="ua">Europe/Uzhgorod</timezone>
- <timezone code="ua">Europe/Zaporozhye</timezone>
-
- <!-- UGANDA, 3:00 -->
-
- <timezone code="ug">Africa/Kampala</timezone>
-
- <!-- UNITED STATES MINOR OUTLYING ISLANDS, 12:00 -->
-
- <timezone code="um">Pacific/Wake</timezone>
-
- <!-- UNITED STATES MINOR OUTLYING ISLANDS, -11:00 -->
-
- <timezone code="um">Pacific/Midway</timezone>
-
- <!-- UNITED STATES, -5:00 -->
-
- <timezone code="us">America/New_York</timezone>
- <timezone code="us">America/Detroit</timezone>
- <timezone code="us">America/Kentucky/Louisville</timezone>
- <timezone code="us">America/Kentucky/Monticello</timezone>
- <timezone code="us">America/Indiana/Indianapolis</timezone>
- <timezone code="us">America/Indiana/Vincennes</timezone>
- <timezone code="us">America/Indiana/Winamac</timezone>
- <timezone code="us">America/Indiana/Marengo</timezone>
- <timezone code="us">America/Indiana/Petersburg</timezone>
- <timezone code="us">America/Indiana/Vevay</timezone>
-
- <!-- UNITED STATES, -6:00 -->
-
- <timezone code="us">America/Chicago</timezone>
- <timezone code="us">America/Indiana/Knox</timezone>
- <timezone code="us">America/Menominee</timezone>
- <timezone code="us">America/North_Dakota/Center</timezone>
- <timezone code="us">America/North_Dakota/New_Salem</timezone>
- <timezone code="us">America/Indiana/Tell_City</timezone>
- <timezone code="us">America/North_Dakota/Beulah</timezone>
-
- <!-- UNITED STATES, -7:00 -->
-
- <timezone code="us">America/Denver</timezone>
- <timezone code="us">America/Boise</timezone>
- <timezone code="us">America/Phoenix</timezone>
-
- <!-- UNITED STATES, -8:00 -->
-
- <timezone code="us">America/Los_Angeles</timezone>
-
- <!-- UNITED STATES, -9:00 -->
-
- <timezone code="us">America/Anchorage</timezone>
- <timezone code="us">America/Juneau</timezone>
- <timezone code="us">America/Yakutat</timezone>
- <timezone code="us">America/Nome</timezone>
- <timezone code="us">America/Metlakatla</timezone>
- <timezone code="us">America/Sitka</timezone>
-
- <!-- UNITED STATES, -10:00 -->
-
- <timezone code="us">Pacific/Honolulu</timezone>
- <timezone code="us">America/Adak</timezone>
-
- <!-- URUGUAY, -3:00 -->
-
- <timezone code="uy">America/Montevideo</timezone>
-
- <!-- UZBEKISTAN, 5:00 -->
-
- <timezone code="uz">Asia/Tashkent</timezone>
- <timezone code="uz">Asia/Samarkand</timezone>
-
- <!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
-
- <timezone code="va">Europe/Vatican</timezone>
-
- <!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
-
- <timezone code="vc">America/St_Vincent</timezone>
-
- <!-- VENEZUELA, -4:00 -->
-
- <timezone code="ve">America/Caracas</timezone>
-
- <!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
-
- <timezone code="vg">America/Tortola</timezone>
-
- <!-- VIRGIN ISLANDS, U.S., -4:00 -->
-
- <timezone code="vi">America/St_Thomas</timezone>
-
- <!-- VIET NAM, 7:00 -->
-
- <timezone code="vn">Asia/Ho_Chi_Minh</timezone>
-
- <!-- VANUATU, 11:00 -->
-
- <timezone code="vu">Pacific/Efate</timezone>
-
- <!-- WALLIS AND FUTUNA, 12:00 -->
-
- <timezone code="wf">Pacific/Wallis</timezone>
-
- <!-- SAMOA, 13:00 -->
-
- <timezone code="ws">Pacific/Apia</timezone>
-
- <!-- YEMEN, 3:00 -->
-
- <timezone code="ye">Asia/Aden</timezone>
-
- <!-- MAYOTTE, 3:00 -->
-
- <timezone code="yt">Indian/Mayotte</timezone>
-
- <!-- SOUTH AFRICA, 2:00 -->
-
- <timezone code="za">Africa/Johannesburg</timezone>
-
- <!-- ZAMBIA, 2:00 -->
-
- <timezone code="zm">Africa/Lusaka</timezone>
-
- <!-- ZIMBABWE, 2:00 -->
-
- <timezone code="zw">Africa/Harare</timezone>
-</timezones>
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/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/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 2ec9f23..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);
}
}
@@ -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/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 985a12c..71201ce 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -193,6 +193,11 @@
private static final int IPV4_ANY_HOST_ADDRESS = 0;
private static final int IPV4_BROADCAST_ADDRESS = -1; // 255.255.255.255
+ // Traffic class and Flow label are not byte aligned. Luckily we
+ // don't care about either value so we'll consider bytes 1-3 of the
+ // IPv6 header as don't care.
+ private static final int IPV6_FLOW_LABEL_OFFSET = ETH_HEADER_LEN + 1;
+ private static final int IPV6_FLOW_LABEL_LEN = 3;
private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
@@ -472,8 +477,13 @@
RaEvent.Builder builder = new RaEvent.Builder();
- // Ignore the checksum.
+ // Ignore the flow label and low 4 bits of traffic class.
int lastNonLifetimeStart = addNonLifetime(0,
+ IPV6_FLOW_LABEL_OFFSET,
+ IPV6_FLOW_LABEL_LEN);
+
+ // Ignore the checksum.
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
ICMP6_RA_CHECKSUM_OFFSET,
ICMP6_RA_CHECKSUM_LEN);
@@ -564,9 +574,14 @@
for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
+ // The flow label is in mNonLifetimes, but it's not a lifetime.
+ if (offset == IPV6_FLOW_LABEL_OFFSET) {
+ continue;
+ }
+
// The checksum is in mNonLifetimes, but it's not a lifetime.
if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
- continue;
+ continue;
}
final int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
@@ -628,6 +643,11 @@
if ((i + 1) < mNonLifetimes.size()) {
Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
int offset = nonLifetime.first + nonLifetime.second;
+
+ // Skip the Flow label.
+ if (offset == IPV6_FLOW_LABEL_OFFSET) {
+ continue;
+ }
// Skip the checksum.
if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
continue;
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 6107895..640c9e1 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -269,6 +269,23 @@
}
/**
+ * Dumps the events in a timeline format.
+ * @param pw The {@link IndentingPrintWriter} to write to.
+ * @hide
+ */
+ public static void dumpEventsTimeline(IndentingPrintWriter pw) {
+ // If the Events logger has not been initialized, then there have been no events logged.
+ // Don't load it now!
+ synchronized (sSingletonSync) {
+ if (sEventManager != null) {
+ getEventManager().dumpEventsTimeline(pw);
+ } else {
+ pw.println("No Historical Events Logged.");
+ }
+ }
+ }
+
+ /**
* Enable or disable extended telecom logging.
*
* @param isExtendedLoggingEnabled {@code true} if extended logging should be enabled,
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 2cd1b96..fddbfce 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.telecom.Log;
import android.text.TextUtils;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
@@ -27,6 +28,7 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.IllegalFormatException;
@@ -35,6 +37,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.stream.Collectors;
/**
* A utility class that provides the ability to define Events that a subsystem deems important, and
@@ -49,6 +52,7 @@
public static final String TAG = "Logging.Events";
@VisibleForTesting
public static final int DEFAULT_EVENTS_TO_CACHE = 10; // Arbitrarily chosen.
+ private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
public interface Loggable {
/**
@@ -169,7 +173,6 @@
}
}
- private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
private final List<Event> mEvents = new LinkedList<>();
private final Loggable mRecordEntry;
@@ -308,6 +311,41 @@
pw.decreaseIndent();
}
+ /**
+ * Dumps events in a timeline format.
+ * @param pw The {@link IndentingPrintWriter} to output the timeline to.
+ * @hide
+ */
+ public void dumpEventsTimeline(IndentingPrintWriter pw) {
+ pw.println("Historical Events (sorted by time):");
+
+ // Flatten event records out for sorting.
+ List<Pair<Loggable, Event>> events = new ArrayList<>();
+ for (EventRecord er : mEventRecords) {
+ for (Event ev : er.getEvents()) {
+ events.add(new Pair<>(er.getRecordEntry(), ev));
+ }
+ }
+
+ // Sort by event time.
+ Comparator<Pair<Loggable, Event>> byEventTime = (e1, e2) -> {
+ return Long.compare(e1.second.time, e2.second.time);
+ };
+ events.sort(byEventTime);
+
+ pw.increaseIndent();
+ for (Pair<Loggable, Event> event : events) {
+ pw.print(sDateFormat.format(new Date(event.second.time)));
+ pw.print(",");
+ pw.print(event.first.getId());
+ pw.print(",");
+ pw.print(event.second.eventId);
+ pw.print(",");
+ pw.println(event.second.data);
+ }
+ pw.decreaseIndent();
+ }
+
public void changeEventCacheSize(int newSize) {
// Resize the event queue.
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/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/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index d4896264..6bf3b6b 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -1066,10 +1066,15 @@
final int ROUTE_LIFETIME = 400;
// Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
final int DNSSL_LIFETIME = 2000;
+ final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
+ // IPv6, traffic class = 0, flow label = 0x12345
+ final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
// Verify RA is passed the first time
ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
+ VERSION_TRAFFIC_CLASS_FLOW_LABEL);
basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
@@ -1080,6 +1085,13 @@
testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
+ ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
+ basePacket.clear();
+ newFlowLabelPacket.put(basePacket);
+ // Check that changes are ignored in every byte of the flow label.
+ newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
+ VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
+
// Ensure zero-length options cause the packet to be silently skipped.
// Do this before we test other packets. http://b/29586253
ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
@@ -1145,6 +1157,7 @@
// Verify that current program filters all five RAs:
program = ipManagerCallback.getApfProgram();
verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
+ verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
diff --git a/tests/CoreTests/android/core/NsdServiceInfoTest.java b/tests/net/java/android/net/nsd/NsdServiceInfoTest.java
similarity index 78%
rename from tests/CoreTests/android/core/NsdServiceInfoTest.java
rename to tests/net/java/android/net/nsd/NsdServiceInfoTest.java
index 5bf0167..e48b522 100644
--- a/tests/CoreTests/android/core/NsdServiceInfoTest.java
+++ b/tests/net/java/android/net/nsd/NsdServiceInfoTest.java
@@ -1,11 +1,32 @@
-package android.core;
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-import android.test.AndroidTestCase;
+package android.net.nsd;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.os.Bundle;
import android.os.Parcel;
import android.os.StrictMode;
import android.net.nsd.NsdServiceInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import java.util.Arrays;
@@ -14,8 +35,12 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class NsdServiceInfoTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NsdServiceInfoTest {
public final static InetAddress LOCALHOST;
static {
@@ -30,6 +55,7 @@
LOCALHOST = _host;
}
+ @Test
public void testLimits() throws Exception {
NsdServiceInfo info = new NsdServiceInfo();
@@ -85,6 +111,7 @@
assertTrue(info.getTxtRecord().length == 1300);
}
+ @Test
public void testParcel() throws Exception {
NsdServiceInfo emptyInfo = new NsdServiceInfo();
checkParcelable(emptyInfo);
@@ -139,25 +166,25 @@
NsdServiceInfo result = reader.getParcelable("test_info");
// Assert equality of base fields.
- assertEquality(original.getServiceName(), result.getServiceName());
- assertEquality(original.getServiceType(), result.getServiceType());
- assertEquality(original.getHost(), result.getHost());
+ assertEquals(original.getServiceName(), result.getServiceName());
+ assertEquals(original.getServiceType(), result.getServiceType());
+ assertEquals(original.getHost(), result.getHost());
assertTrue(original.getPort() == result.getPort());
// Assert equality of attribute map.
Map<String, byte[]> originalMap = original.getAttributes();
Map<String, byte[]> resultMap = result.getAttributes();
- assertEquality(originalMap.keySet(), resultMap.keySet());
+ assertEquals(originalMap.keySet(), resultMap.keySet());
for (String key : originalMap.keySet()) {
assertTrue(Arrays.equals(originalMap.get(key), resultMap.get(key)));
}
}
- public void assertEquality(Object expected, Object result) {
- assertTrue(expected == result || expected.equals(result));
- }
-
public void assertEmptyServiceInfo(NsdServiceInfo shouldBeEmpty) {
- assertTrue(null == shouldBeEmpty.getTxtRecord());
+ byte[] txtRecord = shouldBeEmpty.getTxtRecord();
+ if (txtRecord == null || txtRecord.length == 0) {
+ return;
+ }
+ fail("NsdServiceInfo.getTxtRecord did not return null but " + Arrays.toString(txtRecord));
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index bbbf626..00b0f98 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -115,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";
@@ -223,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.
@@ -243,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());
}
}
@@ -344,18 +363,10 @@
};
// 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);
@@ -802,13 +813,22 @@
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;
@@ -840,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));
@@ -911,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);
@@ -934,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);
@@ -1290,7 +1311,7 @@
}
void assertNoCallback() {
- mService.waitForIdle();
+ waitForIdle();
CallbackInfo c = mCallbacks.peek();
assertNull("Unexpected callback: " + c, c);
}
@@ -1331,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());
@@ -1369,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());
@@ -1481,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.
@@ -1842,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);
@@ -1877,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);
@@ -2294,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) {
@@ -2336,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.
@@ -2392,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);
@@ -2404,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,
@@ -2419,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);
@@ -2466,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;
}
@@ -2520,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);
@@ -2549,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());
@@ -2559,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());
}
@@ -2714,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);
@@ -2902,7 +2929,7 @@
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
mWiFiNetworkAgent.sendLinkProperties(lp);
- mService.waitForIdle();
+ waitForIdle();
return mWiFiNetworkAgent.getNetwork();
}
@@ -2981,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();
@@ -2996,7 +3023,7 @@
ka.stop();
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
- mService.waitForIdle();
+ waitForIdle();
callback.expectStopped();
// Reconnect.
@@ -3197,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++) {
@@ -3205,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");
+ }
+ }
+
}