use of com.android.internal.annotations.VisibleForTesting in project android_frameworks_base by ResurrectionRemix.
the class ApfFilter method maybeStartFilter.
/**
* Attempt to start listening for RAs and, if RAs are received, generating and installing
* filters to ignore useless RAs.
*/
@VisibleForTesting
void maybeStartFilter() {
FileDescriptor socket;
try {
mHardwareAddress = mNetworkInterface.getHardwareAddress();
synchronized (this) {
// Install basic filters
installNewProgramLocked();
}
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, mNetworkInterface.getIndex());
Os.bind(socket, addr);
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
} catch (SocketException | ErrnoException e) {
Log.e(TAG, "Error starting filter", e);
return;
}
mReceiveThread = new ReceiveThread(socket);
mReceiveThread.start();
}
use of com.android.internal.annotations.VisibleForTesting in project android_frameworks_base by ResurrectionRemix.
the class NetworkMonitor method sendHttpProbe.
/**
* Do a URL fetch on a known web server to see if we get the data we expect.
* @return a CaptivePortalProbeResult inferred from the HTTP response.
*/
@VisibleForTesting
protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) {
HttpURLConnection urlConnection = null;
int httpResponseCode = 599;
String redirectUrl = null;
final Stopwatch probeTimer = new Stopwatch().start();
try {
urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setUseCaches(false);
final String userAgent = getCaptivePortalUserAgent(mContext);
if (userAgent != null) {
urlConnection.setRequestProperty("User-Agent", userAgent);
}
// Time how long it takes to get a response to our request
long requestTimestamp = SystemClock.elapsedRealtime();
httpResponseCode = urlConnection.getResponseCode();
redirectUrl = urlConnection.getHeaderField("location");
// Time how long it takes to get a response to our request
long responseTimestamp = SystemClock.elapsedRealtime();
validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url + " time=" + (responseTimestamp - requestTimestamp) + "ms" + " ret=" + httpResponseCode + " headers=" + urlConnection.getHeaderFields());
// proxy server.
if (httpResponseCode == 200) {
if (probeType == ValidationProbeEvent.PROBE_PAC) {
validationLog("PAC fetch 200 response interpreted as 204 response.");
httpResponseCode = 204;
} else if (urlConnection.getContentLengthLong() == 0) {
// Consider 200 response with "Content-length=0" to not be a captive portal.
// There's no point in considering this a captive portal as the user cannot
// sign-in to an empty page. Probably the result of a broken transparent proxy.
// See http://b/9972012.
validationLog("200 response with Content-length=0 interpreted as 204 response.");
httpResponseCode = 204;
} else if (urlConnection.getContentLengthLong() == -1) {
// response. Do not use available() as it is unreliable. See http://b/33498325.
if (urlConnection.getInputStream().read() == -1) {
validationLog("Empty 200 response interpreted as 204 response.");
httpResponseCode = 204;
}
}
}
} catch (IOException e) {
validationLog("Probably not a portal: exception " + e);
if (httpResponseCode == 599) {
// TODO: Ping gateway and DNS server and log results.
}
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
logValidationProbe(probeTimer.stop(), probeType, httpResponseCode);
return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString());
}
use of com.android.internal.annotations.VisibleForTesting in project android_frameworks_base by ResurrectionRemix.
the class NetworkMonitor method isCaptivePortal.
@VisibleForTesting
protected CaptivePortalProbeResult isCaptivePortal() {
if (!mIsCaptivePortalCheckEnabled) {
validationLog("Validation disabled.");
return new CaptivePortalProbeResult(204);
}
URL pacUrl = null, httpsUrl = null, httpUrl = null, fallbackUrl = null;
// On networks with a PAC instead of fetching a URL that should result in a 204
// response, we instead simply fetch the PAC script. This is done for a few reasons:
// 1. At present our PAC code does not yet handle multiple PACs on multiple networks
// until something like https://android-review.googlesource.com/#/c/115180/ lands.
// Network.openConnection() will ignore network-specific PACs and instead fetch
// using NO_PROXY. If a PAC is in place, the only fetch we know will succeed with
// NO_PROXY is the fetch of the PAC itself.
// 2. To proxy the generate_204 fetch through a PAC would require a number of things
// happen before the fetch can commence, namely:
// a) the PAC script be fetched
// b) a PAC script resolver service be fired up and resolve the captive portal
// server.
// Network validation could be delayed until these prerequisities are satisifed or
// could simply be left to race them. Neither is an optimal solution.
// 3. PAC scripts are sometimes used to block or restrict Internet access and may in
// fact block fetching of the generate_204 URL which would lead to false negative
// results for network validation.
final ProxyInfo proxyInfo = mNetworkAgentInfo.linkProperties.getHttpProxy();
if (proxyInfo != null && !Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) {
pacUrl = makeURL(proxyInfo.getPacFileUrl().toString());
if (pacUrl == null) {
return CaptivePortalProbeResult.FAILED;
}
}
if (pacUrl == null) {
httpsUrl = makeURL(getCaptivePortalServerHttpsUrl(mContext));
httpUrl = makeURL(getCaptivePortalServerHttpUrl(mContext));
fallbackUrl = makeURL(getCaptivePortalFallbackUrl(mContext));
if (httpUrl == null || httpsUrl == null) {
return CaptivePortalProbeResult.FAILED;
}
}
long startTime = SystemClock.elapsedRealtime();
final CaptivePortalProbeResult result;
if (pacUrl != null) {
result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
} else if (mUseHttps) {
result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl);
} else {
result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
long endTime = SystemClock.elapsedRealtime();
sendNetworkConditionsBroadcast(true, /* response received */
result.isPortal(), /* isCaptivePortal */
startTime, endTime);
return result;
}
use of com.android.internal.annotations.VisibleForTesting in project android_frameworks_base by ResurrectionRemix.
the class InputMethodUtils method parseInputMethodsAndSubtypesString.
/**
* Parses the setting stored input methods and subtypes string value.
*
* @param inputMethodsAndSubtypesString The input method subtypes value stored in settings.
* @return Map from input method ID to set of input method subtypes IDs.
*/
@VisibleForTesting
public static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString(@Nullable final String inputMethodsAndSubtypesString) {
final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<>();
if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
return imeMap;
}
final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR);
final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR);
List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter);
for (Pair<String, ArrayList<String>> ime : allImeSettings) {
ArraySet<String> subtypes = new ArraySet<>();
if (ime.second != null) {
subtypes.addAll(ime.second);
}
imeMap.put(ime.first, subtypes);
}
return imeMap;
}
use of com.android.internal.annotations.VisibleForTesting in project android_frameworks_base by ResurrectionRemix.
the class LocaleUtils method filterByLanguage.
/**
* Filters the given items based on language preferences.
*
* <p>For each language found in {@code preferredLanguages}, this method tries to copy at most
* one best-match item from {@code source} to {@code dest}. For example, if
* {@code "en-GB", "ja", "en-AU", "fr-CA", "en-IN"} is specified to {@code preferredLanguages},
* this method tries to copy at most one English locale, at most one Japanese, and at most one
* French locale from {@code source} to {@code dest}. Here the best matching English locale
* will be searched from {@code source} based on matching score. For the score design, see
* {@link LocaleUtils#calculateMatchingScore(ULocale, LocaleList, byte[])}</p>
*
* @param sources Source items to be filtered.
* @param extractor Type converter from the source items to {@link Locale} object.
* @param preferredLanguages Ordered list of locales with which the input items will be
* filtered.
* @param dest Destination into which the filtered items will be added.
* @param <T> Type of the data items.
*/
@VisibleForTesting
public static <T> void filterByLanguage(@NonNull List<T> sources, @NonNull LocaleExtractor<T> extractor, @NonNull LocaleList preferredLanguages, @NonNull ArrayList<T> dest) {
final HashMap<String, ScoreEntry> scoreboard = new HashMap<>();
final byte[] score = new byte[preferredLanguages.size()];
final int sourceSize = sources.size();
for (int i = 0; i < sourceSize; ++i) {
final Locale locale = extractor.get(sources.get(i));
if (locale == null || !calculateMatchingScore(ULocale.addLikelySubtags(ULocale.forLocale(locale)), preferredLanguages, score)) {
continue;
}
final String lang = locale.getLanguage();
final ScoreEntry bestScore = scoreboard.get(lang);
if (bestScore == null) {
scoreboard.put(lang, new ScoreEntry(score, i));
} else {
bestScore.updateIfBetter(score, i);
}
}
final ScoreEntry[] result = scoreboard.values().toArray(new ScoreEntry[scoreboard.size()]);
Arrays.sort(result);
for (final ScoreEntry entry : result) {
dest.add(sources.get(entry.mIndex));
}
}
Aggregations