Merge "Uses bound service instead of ordered broadcast for IPC."
This commit is contained in:
committed by
Android (Google) Code Review
commit
a1edd8ad67
@@ -17,6 +17,8 @@ LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := com/android/cts/net/hostside/IRemoteSocketFactory.aidl
|
||||
LOCAL_SRC_FILES := \
|
||||
com/android/cts/net/hostside/IMyService.aidl \
|
||||
com/android/cts/net/hostside/IRemoteSocketFactory.aidl
|
||||
LOCAL_MODULE := CtsHostsideNetworkTestsAidl
|
||||
include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.cts.net.hostside;
|
||||
|
||||
interface IMyService {
|
||||
void registerBroadcastReceiver();
|
||||
int getCounters(String receiverName, String action);
|
||||
String checkNetworkStatus();
|
||||
String getRestrictBackgroundStatus();
|
||||
void sendNotification(int notificationId, String notificationType);
|
||||
}
|
||||
@@ -54,25 +54,11 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
// Constants below must match values defined on app2's Common.java
|
||||
private static final String MANIFEST_RECEIVER = "ManifestReceiver";
|
||||
private static final String DYNAMIC_RECEIVER = "DynamicReceiver";
|
||||
private static final String ACTION_GET_COUNTERS =
|
||||
"com.android.cts.net.hostside.app2.action.GET_COUNTERS";
|
||||
private static final String ACTION_GET_RESTRICT_BACKGROUND_STATUS =
|
||||
"com.android.cts.net.hostside.app2.action.GET_RESTRICT_BACKGROUND_STATUS";
|
||||
private static final String ACTION_CHECK_NETWORK =
|
||||
"com.android.cts.net.hostside.app2.action.CHECK_NETWORK";
|
||||
|
||||
private static final String ACTION_RECEIVER_READY =
|
||||
"com.android.cts.net.hostside.app2.action.RECEIVER_READY";
|
||||
static final String ACTION_SEND_NOTIFICATION =
|
||||
"com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION";
|
||||
static final String ACTION_SHOW_TOAST =
|
||||
"com.android.cts.net.hostside.app2.action.SHOW_TOAST";
|
||||
private static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
|
||||
private static final String EXTRA_RECEIVER_NAME =
|
||||
"com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
|
||||
private static final String EXTRA_NOTIFICATION_ID =
|
||||
"com.android.cts.net.hostside.app2.extra.NOTIFICATION_ID";
|
||||
private static final String EXTRA_NOTIFICATION_TYPE =
|
||||
"com.android.cts.net.hostside.app2.extra.NOTIFICATION_TYPE";
|
||||
|
||||
protected static final String NOTIFICATION_TYPE_CONTENT = "CONTENT";
|
||||
protected static final String NOTIFICATION_TYPE_DELETE = "DELETE";
|
||||
@@ -99,6 +85,7 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
protected WifiManager mWfm;
|
||||
protected int mUid;
|
||||
private String mMeteredWifi;
|
||||
private MyServiceClient mServiceClient;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
@@ -110,12 +97,21 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
|
||||
mUid = getUid(TEST_APP2_PKG);
|
||||
final int myUid = getUid(mContext.getPackageName());
|
||||
mServiceClient = new MyServiceClient(mContext);
|
||||
mServiceClient.bind();
|
||||
|
||||
Log.i(TAG, "Apps status on " + getName() + ":\n"
|
||||
+ "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
|
||||
+ "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
mServiceClient.unbind();
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected int getUid(String packageName) throws Exception {
|
||||
return mContext.getPackageManager().getPackageUid(packageName, 0);
|
||||
}
|
||||
@@ -171,19 +167,13 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
}
|
||||
|
||||
protected int getNumberBroadcastsReceived(String receiverName, String action) throws Exception {
|
||||
final Intent intent = new Intent(ACTION_GET_COUNTERS);
|
||||
intent.putExtra(EXTRA_ACTION, ACTION_RESTRICT_BACKGROUND_CHANGED);
|
||||
intent.putExtra(EXTRA_RECEIVER_NAME, receiverName);
|
||||
final String resultData = sendOrderedBroadcast(intent);
|
||||
assertNotNull("timeout waiting for ordered broadcast result", resultData);
|
||||
return Integer.valueOf(resultData);
|
||||
return mServiceClient.getCounters(receiverName, action);
|
||||
}
|
||||
|
||||
protected void assertRestrictBackgroundStatus(int expectedStatus) throws Exception {
|
||||
final Intent intent = new Intent(ACTION_GET_RESTRICT_BACKGROUND_STATUS);
|
||||
final String resultData = sendOrderedBroadcast(intent);
|
||||
assertNotNull("timeout waiting for ordered broadcast result", resultData);
|
||||
final String actualStatus = toString(Integer.parseInt(resultData));
|
||||
final String status = mServiceClient.getRestrictBackgroundStatus();
|
||||
assertNotNull("didn't get API status from app2", status);
|
||||
final String actualStatus = toString(Integer.parseInt(status));
|
||||
assertEquals("wrong status", toString(expectedStatus), actualStatus);
|
||||
}
|
||||
|
||||
@@ -329,15 +319,15 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
* @return error message with the mismatch (or empty if assertion passed).
|
||||
*/
|
||||
private String checkNetworkAccess(boolean expectAvailable) throws Exception {
|
||||
String resultData = sendOrderedBroadcast(new Intent(ACTION_CHECK_NETWORK));
|
||||
final String resultData = mServiceClient.checkNetworkStatus();
|
||||
if (resultData == null) {
|
||||
return "timeout waiting for ordered broadcast";
|
||||
return "did not get network status from app2";
|
||||
}
|
||||
// Network status format is described on MyBroadcastReceiver.checkNetworkStatus()
|
||||
final String[] parts = resultData.split(NETWORK_STATUS_SEPARATOR);
|
||||
assertEquals("Wrong network status: " + resultData, 5, parts.length); // Sanity check
|
||||
final State state = State.valueOf(parts[0]);
|
||||
final DetailedState detailedState = DetailedState.valueOf(parts[1]);
|
||||
final State state = parts[0].equals("null") ? null : State.valueOf(parts[0]);
|
||||
final DetailedState detailedState = parts[1].equals("null") ? null : DetailedState.valueOf(parts[1]);
|
||||
final boolean connected = Boolean.valueOf(parts[2]);
|
||||
final String connectionCheckDetails = parts[3];
|
||||
final String networkInfo = parts[4];
|
||||
@@ -694,9 +684,10 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
* {@link #runDeviceTests(String, String)} is executed.
|
||||
*/
|
||||
protected void registerBroadcastReceiver() throws Exception {
|
||||
executeShellCommand("am startservice com.android.cts.net.hostside.app2/.MyService");
|
||||
mServiceClient.registerBroadcastReceiver();
|
||||
|
||||
// Wait until receiver is ready.
|
||||
final int maxTries = 5;
|
||||
final int maxTries = 10;
|
||||
for (int i = 1; i <= maxTries; i++) {
|
||||
final String message =
|
||||
sendOrderedBroadcast(new Intent(ACTION_RECEIVER_READY), SECOND_IN_MS);
|
||||
@@ -781,13 +772,10 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
+ "--receiver-foreground --receiver-registered-only");
|
||||
}
|
||||
|
||||
protected void sendNotification(int notificationId, String notificationType) {
|
||||
final Intent intent = new Intent(ACTION_SEND_NOTIFICATION);
|
||||
intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
|
||||
intent.putExtra(EXTRA_NOTIFICATION_TYPE, notificationType);
|
||||
Log.d(TAG, "Sending notification broadcast (id=" + notificationId + ", type="
|
||||
+ notificationType + ": " + intent);
|
||||
mContext.sendBroadcast(intent);
|
||||
protected void sendNotification(int notificationId, String notificationType) throws Exception {
|
||||
Log.d(TAG, "Sending notification broadcast (id=" + notificationId
|
||||
+ ", type=" + notificationType);
|
||||
mServiceClient.sendNotification(notificationId, notificationType);
|
||||
}
|
||||
|
||||
protected String showToast() {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.cts.net.hostside;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.cts.net.hostside.IMyService;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
public class MyServiceClient {
|
||||
private static final int TIMEOUT_MS = 5000;
|
||||
private static final String PACKAGE = MyServiceClient.class.getPackage().getName();
|
||||
private static final String APP2_PACKAGE = PACKAGE + ".app2";
|
||||
private static final String SERVICE_NAME = APP2_PACKAGE + ".MyService";
|
||||
|
||||
private Context mContext;
|
||||
private ServiceConnection mServiceConnection;
|
||||
private IMyService mService;
|
||||
|
||||
public MyServiceClient(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
if (mService != null) {
|
||||
throw new IllegalStateException("Already bound");
|
||||
}
|
||||
|
||||
final ConditionVariable cv = new ConditionVariable();
|
||||
mServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mService = IMyService.Stub.asInterface(service);
|
||||
cv.open();
|
||||
}
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mService = null;
|
||||
}
|
||||
};
|
||||
|
||||
final Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName(APP2_PACKAGE, SERVICE_NAME));
|
||||
// Needs to use BIND_ALLOW_OOM_MANAGEMENT and BIND_NOT_FOREGROUND so app2 does not run in
|
||||
// the same process state as app
|
||||
mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE
|
||||
| Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_FOREGROUND);
|
||||
cv.block(TIMEOUT_MS);
|
||||
if (mService == null) {
|
||||
throw new IllegalStateException(
|
||||
"Could not bind to MyService service after " + TIMEOUT_MS + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
if (mService != null) {
|
||||
mContext.unbindService(mServiceConnection);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerBroadcastReceiver() throws RemoteException {
|
||||
mService.registerBroadcastReceiver();
|
||||
}
|
||||
|
||||
public int getCounters(String receiverName, String action) throws RemoteException {
|
||||
return mService.getCounters(receiverName, action);
|
||||
}
|
||||
|
||||
public String checkNetworkStatus() throws RemoteException {
|
||||
return mService.checkNetworkStatus();
|
||||
}
|
||||
|
||||
public String getRestrictBackgroundStatus() throws RemoteException {
|
||||
return mService.getRestrictBackgroundStatus();
|
||||
}
|
||||
|
||||
public void sendNotification(int notificationId, String notificationType) throws RemoteException {
|
||||
mService.sendNotification(notificationId, notificationType);
|
||||
}
|
||||
}
|
||||
@@ -26,27 +26,13 @@ public final class Common {
|
||||
// AbstractRestrictBackgroundNetworkTestCase.java
|
||||
static final String MANIFEST_RECEIVER = "ManifestReceiver";
|
||||
static final String DYNAMIC_RECEIVER = "DynamicReceiver";
|
||||
static final String ACTION_GET_COUNTERS =
|
||||
"com.android.cts.net.hostside.app2.action.GET_COUNTERS";
|
||||
static final String ACTION_GET_RESTRICT_BACKGROUND_STATUS =
|
||||
"com.android.cts.net.hostside.app2.action.GET_RESTRICT_BACKGROUND_STATUS";
|
||||
static final String ACTION_CHECK_NETWORK =
|
||||
"com.android.cts.net.hostside.app2.action.CHECK_NETWORK";
|
||||
|
||||
static final String ACTION_RECEIVER_READY =
|
||||
"com.android.cts.net.hostside.app2.action.RECEIVER_READY";
|
||||
static final String ACTION_FINISH_ACTIVITY =
|
||||
"com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
|
||||
static final String ACTION_SEND_NOTIFICATION =
|
||||
"com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION";
|
||||
static final String ACTION_SHOW_TOAST =
|
||||
"com.android.cts.net.hostside.app2.action.SHOW_TOAST";
|
||||
static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
|
||||
static final String EXTRA_RECEIVER_NAME =
|
||||
"com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
|
||||
static final String EXTRA_NOTIFICATION_ID =
|
||||
"com.android.cts.net.hostside.app2.extra.NOTIFICATION_ID";
|
||||
static final String EXTRA_NOTIFICATION_TYPE =
|
||||
"com.android.cts.net.hostside.app2.extra.NOTIFICATION_TYPE";
|
||||
|
||||
static final String NOTIFICATION_TYPE_CONTENT = "CONTENT";
|
||||
static final String NOTIFICATION_TYPE_DELETE = "DELETE";
|
||||
|
||||
@@ -18,16 +18,8 @@ package com.android.cts.net.hostside.app2;
|
||||
|
||||
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
|
||||
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_CHECK_NETWORK;
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_GET_COUNTERS;
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_GET_RESTRICT_BACKGROUND_STATUS;
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_SEND_NOTIFICATION;
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_SHOW_TOAST;
|
||||
import static com.android.cts.net.hostside.app2.Common.EXTRA_ACTION;
|
||||
import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_ID;
|
||||
import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_TYPE;
|
||||
import static com.android.cts.net.hostside.app2.Common.EXTRA_RECEIVER_NAME;
|
||||
import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER;
|
||||
import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION;
|
||||
import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION_BUNDLE;
|
||||
@@ -56,14 +48,12 @@ import android.widget.Toast;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Receiver used to:
|
||||
* <ol>
|
||||
* <li>Stored received RESTRICT_BACKGROUND_CHANGED broadcasts in a shared preference.
|
||||
* <li>Returned the number of RESTRICT_BACKGROUND_CHANGED broadcasts in an ordered broadcast.
|
||||
* <li>Count number of {@code RESTRICT_BACKGROUND_CHANGED} broadcasts received.
|
||||
* <li>Show a toast.
|
||||
* </ol>
|
||||
*/
|
||||
public class MyBroadcastReceiver extends BroadcastReceiver {
|
||||
@@ -89,23 +79,11 @@ public class MyBroadcastReceiver extends BroadcastReceiver {
|
||||
case ACTION_RESTRICT_BACKGROUND_CHANGED:
|
||||
increaseCounter(context, action);
|
||||
break;
|
||||
case ACTION_GET_COUNTERS:
|
||||
setResultDataFromCounter(context, intent);
|
||||
break;
|
||||
case ACTION_GET_RESTRICT_BACKGROUND_STATUS:
|
||||
getRestrictBackgroundStatus(context, intent);
|
||||
break;
|
||||
case ACTION_CHECK_NETWORK:
|
||||
checkNetwork(context, intent);
|
||||
break;
|
||||
case ACTION_RECEIVER_READY:
|
||||
final String message = mName + " is ready to rumble";
|
||||
Log.d(TAG, message);
|
||||
setResultData(message);
|
||||
break;
|
||||
case ACTION_SEND_NOTIFICATION:
|
||||
sendNotification(context, intent);
|
||||
break;
|
||||
case ACTION_SHOW_TOAST:
|
||||
showToast(context);
|
||||
break;
|
||||
@@ -114,14 +92,20 @@ public class MyBroadcastReceiver extends BroadcastReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[MyBroadcastReceiver: mName=" + mName + "]";
|
||||
}
|
||||
|
||||
private void increaseCounter(Context context, String action) {
|
||||
final SharedPreferences prefs = context.getSharedPreferences(mName, Context.MODE_PRIVATE);
|
||||
final SharedPreferences prefs = context.getApplicationContext()
|
||||
.getSharedPreferences(mName, Context.MODE_PRIVATE);
|
||||
final int value = prefs.getInt(action, 0) + 1;
|
||||
Log.d(TAG, "increaseCounter('" + action + "'): setting '" + mName + "' to " + value);
|
||||
prefs.edit().putInt(action, value).apply();
|
||||
}
|
||||
|
||||
private int getCounter(Context context, String action, String receiverName) {
|
||||
static int getCounter(Context context, String action, String receiverName) {
|
||||
final SharedPreferences prefs = context.getSharedPreferences(receiverName,
|
||||
Context.MODE_PRIVATE);
|
||||
final int value = prefs.getInt(action, 0);
|
||||
@@ -129,29 +113,14 @@ public class MyBroadcastReceiver extends BroadcastReceiver {
|
||||
return value;
|
||||
}
|
||||
|
||||
private void getRestrictBackgroundStatus(Context context, Intent intent) {
|
||||
static String getRestrictBackgroundStatus(Context context) {
|
||||
final ConnectivityManager cm = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
final int apiStatus = cm.getRestrictBackgroundStatus();
|
||||
Log.d(TAG, "getRestrictBackgroundStatus: returning " + apiStatus);
|
||||
setResultData(Integer.toString(apiStatus));
|
||||
return String.valueOf(apiStatus);
|
||||
}
|
||||
|
||||
private void checkNetwork(final Context context, Intent intent) {
|
||||
final ConnectivityManager cm = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
||||
String netStatus = null;
|
||||
try {
|
||||
netStatus = checkNetworkStatus(context, cm);
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Timeout checking network status");
|
||||
}
|
||||
Log.d(TAG, "checkNetwork(): returning " + netStatus);
|
||||
setResultData(netStatus);
|
||||
}
|
||||
|
||||
|
||||
private static final String NETWORK_STATUS_TEMPLATE = "%s|%s|%s|%s|%s";
|
||||
/**
|
||||
* Checks whether the network is available and return a string which can then be send as a
|
||||
@@ -182,71 +151,53 @@ public class MyBroadcastReceiver extends BroadcastReceiver {
|
||||
* </code></pre>
|
||||
*
|
||||
*/
|
||||
private String checkNetworkStatus(final Context context, final ConnectivityManager cm)
|
||||
throws InterruptedException {
|
||||
final LinkedBlockingQueue<String> result = new LinkedBlockingQueue<>(1);
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO: connect to a hostside server instead
|
||||
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 status = String.format(NETWORK_STATUS_TEMPLATE,
|
||||
networkInfo.getState().name(), networkInfo.getDetailedState().name(),
|
||||
Boolean.toString(checkStatus), checkDetails, networkInfo);
|
||||
Log.d(TAG, "Offering " + status);
|
||||
result.offer(status);
|
||||
}
|
||||
}, mName).start();
|
||||
return result.poll(NETWORK_TIMEOUT_MS * 2, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void setResultDataFromCounter(Context context, Intent intent) {
|
||||
final String action = intent.getStringExtra(EXTRA_ACTION);
|
||||
if (action == null) {
|
||||
Log.e(TAG, "Missing extra '" + EXTRA_ACTION + "' on " + intent);
|
||||
return;
|
||||
// TODO: now that it uses Binder, it counl return a Bundle with the data parts instead...
|
||||
static String checkNetworkStatus(Context context) {
|
||||
final ConnectivityManager cm =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
// TODO: connect to a hostside server instead
|
||||
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;
|
||||
}
|
||||
final String receiverName = intent.getStringExtra(EXTRA_RECEIVER_NAME);
|
||||
if (receiverName == null) {
|
||||
Log.e(TAG, "Missing extra '" + EXTRA_RECEIVER_NAME + "' on " + intent);
|
||||
return;
|
||||
Log.d(TAG, checkDetails);
|
||||
final String state, detailedState;
|
||||
if (networkInfo != null) {
|
||||
state = networkInfo.getState().name();
|
||||
detailedState = networkInfo.getDetailedState().name();
|
||||
} else {
|
||||
state = detailedState = "null";
|
||||
}
|
||||
final int counter = getCounter(context, action, receiverName);
|
||||
setResultData(String.valueOf(counter));
|
||||
final String status = String.format(NETWORK_STATUS_TEMPLATE, state, detailedState,
|
||||
Boolean.valueOf(checkStatus), checkDetails, networkInfo);
|
||||
Log.d(TAG, "Offering " + status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a system notification containing actions with pending intents to launch the app's
|
||||
* main activitiy or service.
|
||||
*/
|
||||
private void sendNotification(Context context, Intent intent) {
|
||||
final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
|
||||
final String notificationType = intent.getStringExtra(EXTRA_NOTIFICATION_TYPE);
|
||||
Log.d(TAG, "sendNotification: id=" + notificationId + ", type=" + notificationType
|
||||
+ ", intent=" + intent);
|
||||
static void sendNotification(Context context, int notificationId, String notificationType ) {
|
||||
Log.d(TAG, "sendNotification: id=" + notificationId + ", type=" + notificationType);
|
||||
final Intent serviceIntent = new Intent(context, MyService.class);
|
||||
final PendingIntent pendingIntent = PendingIntent.getService(context, 0, serviceIntent,
|
||||
notificationId);
|
||||
|
||||
@@ -24,27 +24,74 @@ import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.cts.net.hostside.IMyService;
|
||||
|
||||
/**
|
||||
* Service used to dynamically register a broadcast receiver.
|
||||
*/
|
||||
public class MyService extends Service {
|
||||
|
||||
private MyBroadcastReceiver mReceiver;
|
||||
|
||||
// TODO: move MyBroadcast static functions here - they were kept there to make git diff easier.
|
||||
|
||||
private IMyService.Stub mBinder =
|
||||
new IMyService.Stub() {
|
||||
|
||||
@Override
|
||||
public void registerBroadcastReceiver() {
|
||||
if (mReceiver != null) {
|
||||
Log.d(TAG, "receiver already registered: " + mReceiver);
|
||||
return;
|
||||
}
|
||||
final Context context = getApplicationContext();
|
||||
mReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
|
||||
context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
|
||||
context.registerReceiver(mReceiver,
|
||||
new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
|
||||
Log.d(TAG, "receiver registered");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCounters(String receiverName, String action) {
|
||||
return MyBroadcastReceiver.getCounter(getApplicationContext(), action, receiverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String checkNetworkStatus() {
|
||||
return MyBroadcastReceiver.checkNetworkStatus(getApplicationContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRestrictBackgroundStatus() {
|
||||
return MyBroadcastReceiver.getRestrictBackgroundStatus(getApplicationContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendNotification(int notificationId, String notificationType) {
|
||||
MyBroadcastReceiver
|
||||
.sendNotification(getApplicationContext(), notificationId, notificationType);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.d(TAG, "MyService.onStartCommand: " + intent);
|
||||
final Context context = getApplicationContext();
|
||||
final MyBroadcastReceiver myReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
|
||||
context.registerReceiver(myReceiver, new IntentFilter(ACTION_RECEIVER_READY));
|
||||
context.registerReceiver(myReceiver, new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
|
||||
Log.d(TAG, "receiver registered");
|
||||
return START_STICKY;
|
||||
public void onDestroy() {
|
||||
if (mReceiver != null) {
|
||||
Log.d(TAG, "onDestroy(): unregistering " + mReceiver);
|
||||
getApplicationContext().unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user