Merge "Uses bound service instead of ordered broadcast for IPC."

This commit is contained in:
TreeHugger Robot
2016-10-11 05:43:27 +00:00
committed by Android (Google) Code Review
7 changed files with 263 additions and 163 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -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);
}
}

View File

@@ -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";

View File

@@ -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);

View File

@@ -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();
}
}