Merge "Add tests for verifying network availability on activity start." into oc-dev

This commit is contained in:
Sudheer Shanka
2017-04-06 22:06:14 +00:00
committed by Android (Google) Code Review
9 changed files with 727 additions and 0 deletions

View File

@@ -27,6 +27,10 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
ShortcutManagerTestUtils \
truth-prebuilt
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
LOCAL_SRC_FILES += aidl/com/android/servicestests/aidl/INetworkStateObserver.aidl
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksServicesTests

View File

@@ -48,6 +48,8 @@
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<application>
<uses-library android:name="android.test.runner" />

View File

@@ -0,0 +1,23 @@
# Copyright (C) 2017 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.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_SRC_FILES := \
com/android/servicestests/aidl/INetworkStateObserver.aidl
LOCAL_MODULE := servicestests-aidl
include $(BUILD_STATIC_JAVA_LIBRARY)

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2017 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.
*/
package com.android.servicestests.aidl;
oneway interface INetworkStateObserver {
/**
* {@param resultData} will be in the format
* NetinfoState|NetinfoDetailedState|RealConnectionCheck|RealConnectionCheckDetails|Netinfo.
* For detailed info, see
* servicestests/test-apps/ConnTestApp/.../ConnTestActivity#checkNetworkStatus
*/
void onNetworkStateChecked(String resultData);
}

Binary file not shown.

View File

@@ -0,0 +1,443 @@
/*
* Copyright (C) 2017 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.
*/
package com.android.server.net;
import static android.util.DebugUtils.valueToString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.frameworks.servicestests.R;
import com.android.servicestests.aidl.INetworkStateObserver;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.util.Log;
import libcore.io.IoUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Tests for verifying network availability on activity start.
*
* To run the tests, use
*
* runtest -c com.android.server.net.ConnOnActivityStartTest frameworks-services
*
* or the following steps:
*
* Build: m FrameworksServicesTests
* Install: adb install -r \
* ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
* Run: adb shell am instrument -e class com.android.server.net.ConnOnActivityStartTest -w \
* com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
public class ConnOnActivityStartTest {
private static final String TAG = ConnOnActivityStartTest.class.getSimpleName();
private static final String ACTION_INSTALL_COMPLETE = "com.android.server.net.INSTALL_COMPLETE";
private static final String TEST_APP_URI =
"android.resource://com.android.frameworks.servicestests/raw/conntestapp";
private static final String TEST_PKG = "com.android.servicestests.apps.conntestapp";
private static final String TEST_ACTIVITY_CLASS = TEST_PKG + ".ConnTestActivity";
private static final String ACTION_FINISH_ACTIVITY = TEST_PKG + ".FINISH";
private static final String EXTRA_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
private static final int WAIT_FOR_INSTALL_TIMEOUT_MS = 2000; // 2 sec
private static final int NETWORK_CHECK_TIMEOUT_MS = 6000; // 6 sec
private static final int SCREEN_ON_DELAY_MS = 500; // 0.5 sec
private static final String NETWORK_STATUS_SEPARATOR = "\\|";
private static final int REPEAT_TEST_COUNT = 5;
private static Context mContext;
private static UiDevice mUiDevice;
private static int mTestPkgUid;
@BeforeClass
public static void setUpOnce() throws Exception {
mContext = InstrumentationRegistry.getContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
installAppAndAssertInstalled();
mContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
mTestPkgUid = mContext.getPackageManager().getPackageUid(TEST_PKG, 0);
}
@AfterClass
public static void tearDownOnce() {
mContext.getPackageManager().deletePackage(TEST_PKG,
new IPackageDeleteObserver.Stub() {
@Override
public void packageDeleted(String packageName, int returnCode)
throws RemoteException {
Log.e(TAG, packageName + " deleted, returnCode: " + returnCode);
}
}, 0);
}
@Test
public void testStartActivity_batterySaver() throws Exception {
setBatterySaverMode(true);
try {
testConnOnActivityStart("testStartActivity_batterySaver");
} finally {
setBatterySaverMode(false);
}
}
@Test
public void testStartActivity_dataSaver() throws Exception {
setDataSaverMode(true);
try {
testConnOnActivityStart("testStartActivity_dataSaver");
} finally {
setDataSaverMode(false);
}
}
@Test
public void testStartActivity_dozeMode() throws Exception {
setDozeMode(true);
try {
testConnOnActivityStart("testStartActivity_dozeMode");
} finally {
setDozeMode(false);
}
}
@Test
public void testStartActivity_appStandby() throws Exception {
try{
turnBatteryOff();
setAppIdle(true);
SystemClock.sleep(30000);
turnScreenOn();
startActivityAndCheckNetworkAccess();
} finally {
turnBatteryOn();
setAppIdle(false);
}
}
@Test
public void testStartActivity_backgroundRestrict() throws Exception {
updateRestrictBackgroundBlacklist(true);
try {
testConnOnActivityStart("testStartActivity_backgroundRestrict");
} finally {
updateRestrictBackgroundBlacklist(false);
}
}
private void testConnOnActivityStart(String testName) throws Exception {
for (int i = 1; i <= REPEAT_TEST_COUNT; ++i) {
try {
Log.d(TAG, testName + " Start #" + i);
turnScreenOn();
SystemClock.sleep(SCREEN_ON_DELAY_MS);
startActivityAndCheckNetworkAccess();
Log.d(TAG, testName + " end #" + i);
} finally {
finishActivity();
}
}
}
// TODO: Some of these methods are also used in CTS, so instead of duplicating code,
// create a static library which can be used by both servicestests and cts.
private void setBatterySaverMode(boolean enabled) throws Exception {
if (enabled) {
turnBatteryOff();
executeCommand("settings put global low_power 1");
} else {
executeCommand("settings put global low_power 0");
turnBatteryOn();
}
final String result = executeCommand("settings get global low_power");
assertEquals(enabled ? "1" : "0", result);
}
private void setDataSaverMode(boolean enabled) throws Exception {
executeCommand("cmd netpolicy set restrict-background " + enabled);
final String output = executeCommand("cmd netpolicy get restrict-background");
final String expectedSuffix = enabled ? "enabled" : "disabled";
assertTrue("output '" + output + "' should end with '" + expectedSuffix + "'",
output.endsWith(expectedSuffix));
}
private void setDozeMode(boolean enabled) throws Exception {
if (enabled) {
turnBatteryOff();
turnScreenOff();
executeCommand("dumpsys deviceidle force-idle deep");
} else {
turnScreenOn();
turnBatteryOn();
executeCommand("dumpsys deviceidle unforce");
}
assertDelayedCommandResult("dumpsys deviceidle get deep", enabled ? "IDLE" : "ACTIVE",
5 /* maxTries */, 500 /* napTimeMs */);
}
private void setAppIdle(boolean enabled) throws Exception {
executeCommand("am set-inactive " + TEST_PKG + " " + enabled);
assertDelayedCommandResult("am get-inactive " + TEST_PKG, "Idle=" + enabled,
10 /* maxTries */, 2000 /* napTimeMs */);
}
private void updateRestrictBackgroundBlacklist(boolean add) throws Exception {
if (add) {
executeCommand("cmd netpolicy add restrict-background-blacklist " + mTestPkgUid);
} else {
executeCommand("cmd netpolicy remove restrict-background-blacklist " + mTestPkgUid);
}
assertRestrictBackground("restrict-background-blacklist", mTestPkgUid, add);
}
private void assertRestrictBackground(String list, int uid, boolean expected) throws Exception {
final int maxTries = 5;
boolean actual = false;
final String expectedUid = Integer.toString(uid);
String uids = "";
for (int i = 1; i <= maxTries; i++) {
final String output = executeCommand("cmd netpolicy list " + list);
uids = output.split(":")[1];
for (String candidate : uids.split(" ")) {
actual = candidate.trim().equals(expectedUid);
if (expected == actual) {
return;
}
}
Log.v(TAG, list + " check for uid " + uid + " doesn't match yet (expected "
+ expected + ", got " + actual + "); sleeping 1s before polling again");
SystemClock.sleep(1000);
}
fail(list + " check for uid " + uid + " failed: expected " + expected + ", got " + actual
+ ". Full list: " + uids);
}
private void turnBatteryOff() throws Exception {
executeCommand("cmd battery unplug");
}
private void turnBatteryOn() throws Exception {
executeCommand("cmd battery reset");
}
private void turnScreenOff() throws Exception {
executeCommand("input keyevent KEYCODE_SLEEP");
}
private void turnScreenOn() throws Exception {
executeCommand("input keyevent KEYCODE_WAKEUP");
executeCommand("wm dismiss-keyguard");
}
private String executeCommand(String cmd) throws IOException {
final String result = mUiDevice.executeShellCommand(cmd).trim();
Log.d(TAG, String.format("Result for '%s': %s", cmd, result));
return result;
}
private void assertDelayedCommandResult(String cmd, String expectedResult,
int maxTries, int napTimeMs) throws IOException {
String result = "";
for (int i = 1; i <= maxTries; ++i) {
result = executeCommand(cmd);
if (expectedResult.equals(result)) {
return;
}
Log.v(TAG, "Command '" + cmd + "' returned '" + result + " instead of '"
+ expectedResult + "' on attempt #" + i
+ "; sleeping " + napTimeMs + "ms before trying again");
SystemClock.sleep(napTimeMs);
}
fail("Command '" + cmd + "' did not return '" + expectedResult + "' after "
+ maxTries + " attempts. Last result: '" + result + "'");
}
private void startActivityAndCheckNetworkAccess() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final Intent launchIntent = new Intent().setComponent(
new ComponentName(TEST_PKG, TEST_ACTIVITY_CLASS));
final Bundle extras = new Bundle();
final String[] errors = new String[] {null};
extras.putBinder(EXTRA_NETWORK_STATE_OBSERVER, new INetworkStateObserver.Stub() {
@Override
public void onNetworkStateChecked(String resultData) {
errors[0] = checkForAvailability(resultData);
latch.countDown();
}
});
launchIntent.putExtras(extras);
mContext.startActivity(launchIntent);
if (latch.await(NETWORK_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
if (!errors[0].isEmpty()) {
fail("Network not available for test app " + mTestPkgUid);
}
} else {
fail("Timed out waiting for network availability status from test app " + mTestPkgUid);
}
}
private void finishActivity() {
final Intent finishIntent = new Intent(ACTION_FINISH_ACTIVITY)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcast(finishIntent);
}
private String checkForAvailability(String resultData) {
if (resultData == null) {
assertNotNull("Network status from app2 is null, Uid: " + mTestPkgUid, resultData);
}
// Network status format is described on MyBroadcastReceiver.checkNetworkStatus()
final String[] parts = resultData.split(NETWORK_STATUS_SEPARATOR);
assertEquals("Wrong network status: " + resultData + ", Uid: " + mTestPkgUid,
5, parts.length); // Sanity check
final NetworkInfo.State state = parts[0].equals("null")
? null : NetworkInfo.State.valueOf(parts[0]);
final NetworkInfo.DetailedState detailedState = parts[1].equals("null")
? null : NetworkInfo.DetailedState.valueOf(parts[1]);
final boolean connected = Boolean.valueOf(parts[2]);
final String connectionCheckDetails = parts[3];
final String networkInfo = parts[4];
final StringBuilder errors = new StringBuilder();
final NetworkInfo.State expectedState = NetworkInfo.State.CONNECTED;
final NetworkInfo.DetailedState expectedDetailedState = NetworkInfo.DetailedState.CONNECTED;
if (true != connected) {
errors.append(String.format("External site connection failed: expected %s, got %s\n",
true, connected));
}
if (expectedState != state || expectedDetailedState != detailedState) {
errors.append(String.format("Connection state mismatch: expected %s/%s, got %s/%s\n",
expectedState, expectedDetailedState, state, detailedState));
}
if (errors.length() > 0) {
errors.append("\tnetworkInfo: " + networkInfo + "\n");
errors.append("\tconnectionCheckDetails: " + connectionCheckDetails + "\n");
}
return errors.toString();
}
private static void installAppAndAssertInstalled() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final int[] result = {PackageInstaller.STATUS_SUCCESS};
final BroadcastReceiver installStatusReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String pkgName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME);
if (!TEST_PKG.equals(pkgName)) {
return;
}
result[0] = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
latch.countDown();
}
};
mContext.registerReceiver(installStatusReceiver, new IntentFilter(ACTION_INSTALL_COMPLETE));
try {
installApp();
if (latch.await(WAIT_FOR_INSTALL_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
if (result[0] != PackageInstaller.STATUS_SUCCESS) {
fail("Couldn't install test app, result: "
+ valueToString(PackageInstaller.class, "STATUS_", result[0]));
}
} else {
fail("Timed out waiting for the test app to install");
}
} finally {
mContext.unregisterReceiver(installStatusReceiver);
}
}
private static void installApp() throws Exception {
final Uri packageUri = Uri.parse(TEST_APP_URI);
final InputStream in = mContext.getContentResolver().openInputStream(packageUri);
final PackageInstaller packageInstaller
= mContext.getPackageManager().getPackageInstaller();
final PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setAppPackageName(TEST_PKG);
final int sessionId = packageInstaller.createSession(params);
final PackageInstaller.Session session = packageInstaller.openSession(sessionId);
OutputStream out = null;
try {
out = session.openWrite(TAG, 0, -1);
final byte[] buffer = new byte[65536];
int c;
while ((c = in.read(buffer)) != -1) {
out.write(buffer, 0, c);
}
session.fsync(out);
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
}
session.commit(createIntentSender(mContext, sessionId));
}
private static IntentSender createIntentSender(Context context, int sessionId) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, sessionId, new Intent(ACTION_INSTALL_COMPLETE), 0);
return pendingIntent.getIntentSender();
}
}

View File

@@ -0,0 +1,30 @@
# Copyright (C) 2017 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.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := servicestests-aidl
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := ConnTestApp
LOCAL_CERTIFICATE := platform
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.servicestests.apps.conntestapp">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application>
<activity android:name=".ConnTestActivity"
android:exported="true" />
</application>
</manifest>

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2017 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.
*/
package com.android.servicestests.apps.conntestapp;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import com.android.servicestests.aidl.INetworkStateObserver;
import java.net.HttpURLConnection;
import java.net.URL;
public class ConnTestActivity extends Activity {
private static final String TAG = ConnTestActivity.class.getSimpleName();
private static final String TEST_PKG = ConnTestActivity.class.getPackage().getName();
private static final String ACTION_FINISH_ACTIVITY = TEST_PKG + ".FINISH";
private static final String EXTRA_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
private static final int NETWORK_TIMEOUT_MS = 5 * 1000;
private static final String NETWORK_STATUS_TEMPLATE = "%s|%s|%s|%s|%s";
private BroadcastReceiver finishCommandReceiver = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
notifyNetworkStateObserver();
finishCommandReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ConnTestActivity.this.finish();
}
};
registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY));
}
@Override
public void onStop() {
if (finishCommandReceiver != null) {
unregisterReceiver(finishCommandReceiver);
}
super.onStop();
}
private void notifyNetworkStateObserver() {
if (getIntent() == null) {
return;
}
final Bundle extras = getIntent().getExtras();
if (extras == null) {
return;
}
final INetworkStateObserver observer = INetworkStateObserver.Stub.asInterface(
extras.getBinder(EXTRA_NETWORK_STATE_OBSERVER));
if (observer != null) {
AsyncTask.execute(() -> {
try {
observer.onNetworkStateChecked(checkNetworkStatus(ConnTestActivity.this));
} catch (RemoteException e) {
Log.e(TAG, "Error occured while notifying the observer: " + e);
}
});
}
}
/**
* Checks whether the network is available and return a string which can then be send as a
* result data for the ordered broadcast.
*
* <p>
* The string has the following format:
*
* <p><pre><code>
* NetinfoState|NetinfoDetailedState|RealConnectionCheck|RealConnectionCheckDetails|Netinfo
* </code></pre>
*
* <p>Where:
*
* <ul>
* <li>{@code NetinfoState}: enum value of {@link NetworkInfo.State}.
* <li>{@code NetinfoDetailedState}: enum value of {@link NetworkInfo.DetailedState}.
* <li>{@code RealConnectionCheck}: boolean value of a real connection check (i.e., an attempt
* to access an external website.
* <li>{@code RealConnectionCheckDetails}: if HTTP output core or exception string of the real
* connection attempt
* <li>{@code Netinfo}: string representation of the {@link NetworkInfo}.
* </ul>
*
* For example, if the connection was established fine, the result would be something like:
* <p><pre><code>
* CONNECTED|CONNECTED|true|200|[type: WIFI[], state: CONNECTED/CONNECTED, reason: ...]
* </code></pre>
*/
private String checkNetworkStatus(Context context) {
final ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final String address = "http://example.com";
final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
Log.d(TAG, "Running checkNetworkStatus() on thread "
+ Thread.currentThread().getName() + " for UID " + getUid(context)
+ "\n\tactiveNetworkInfo: " + networkInfo + "\n\tURL: " + address);
boolean checkStatus = false;
String checkDetails = "N/A";
try {
final URL url = new URL(address);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(NETWORK_TIMEOUT_MS);
conn.setConnectTimeout(NETWORK_TIMEOUT_MS / 2);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
final int response = conn.getResponseCode();
checkStatus = true;
checkDetails = "HTTP response for " + address + ": " + response;
} catch (Exception e) {
checkStatus = false;
checkDetails = "Exception getting " + address + ": " + e;
}
Log.d(TAG, checkDetails);
final String state, detailedState;
if (networkInfo != null) {
state = networkInfo.getState().name();
detailedState = networkInfo.getDetailedState().name();
} else {
state = detailedState = "null";
}
final String status = String.format(NETWORK_STATUS_TEMPLATE, state, detailedState,
Boolean.valueOf(checkStatus), checkDetails, networkInfo);
Log.d(TAG, "Offering " + status);
return status;
}
private int getUid(Context context) {
final String packageName = context.getPackageName();
try {
return context.getPackageManager().getPackageUid(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new IllegalStateException("Could not get UID for " + packageName, e);
}
}
}