Merge "Enable background restrictions"
diff --git a/api/current.txt b/api/current.txt
index 96c47ed..2a8d3fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5435,6 +5435,7 @@
method public boolean removeAutomaticZenRule(java.lang.String);
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+ method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -38971,6 +38972,7 @@
method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public android.content.ComponentName startService(android.content.Intent);
+ method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
method public boolean stopService(android.content.Intent);
method public void unbindService(android.content.ServiceConnection);
method public void unregisterReceiver(android.content.BroadcastReceiver);
diff --git a/api/system-current.txt b/api/system-current.txt
index f2e42eb..cab46e5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5620,6 +5620,7 @@
method public boolean removeAutomaticZenRule(java.lang.String);
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+ method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -42219,6 +42220,7 @@
method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public android.content.ComponentName startService(android.content.Intent);
+ method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
method public boolean stopService(android.content.Intent);
method public void unbindService(android.content.ServiceConnection);
method public void unregisterReceiver(android.content.BroadcastReceiver);
diff --git a/api/test-current.txt b/api/test-current.txt
index 96ddfc7..e5ebf29 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5446,6 +5446,7 @@
method public boolean removeAutomaticZenRule(java.lang.String);
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+ method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -39091,6 +39092,7 @@
method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public android.content.ComponentName startService(android.content.Intent);
+ method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
method public boolean stopService(android.content.Intent);
method public void unbindService(android.content.ServiceConnection);
method public void unregisterReceiver(android.content.BroadcastReceiver);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d08bee5..b67e193 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1385,7 +1385,14 @@
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
- return startServiceCommon(service, mUser);
+ return startServiceCommon(service, -1, null, mUser);
+ }
+
+ @Override
+ public ComponentName startServiceInForeground(Intent service,
+ int id, Notification notification) {
+ warnIfCallingFromSystemProcess();
+ return startServiceCommon(service, id, notification, mUser);
}
@Override
@@ -1396,16 +1403,24 @@
@Override
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
- return startServiceCommon(service, user);
+ return startServiceCommon(service, -1, null, user);
}
- private ComponentName startServiceCommon(Intent service, UserHandle user) {
+ @Override
+ public ComponentName startServiceInForegroundAsUser(Intent service,
+ int id, Notification notification, UserHandle user) {
+ return startServiceCommon(service, id, notification, user);
+ }
+
+ private ComponentName startServiceCommon(Intent service, int id, Notification notification,
+ UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
- getContentResolver()), getOpPackageName(), user.getIdentifier());
+ getContentResolver()), id, notification, getOpPackageName(),
+ user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 5824c32..236eb18 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -128,7 +128,8 @@
void finishSubActivity(in IBinder token, in String resultWho, int requestCode);
PendingIntent getRunningServiceControlPanel(in ComponentName service);
ComponentName startService(in IApplicationThread caller, in Intent service,
- in String resolvedType, in String callingPackage, int userId);
+ in String resolvedType, int id, in Notification notification,
+ in String callingPackage, int userId);
int stopService(in IApplicationThread caller, in Intent service,
in String resolvedType, int userId);
int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 3551691..c0aae6d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -24,6 +24,7 @@
import android.app.Notification.Builder;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -1085,4 +1086,38 @@
default: return defValue;
}
}
+
+ /**
+ * Start a service directly into the "foreground service" state. Unlike
+ * {@link android.content.Context#startService(Intent)}, this method
+ * can be used from within background operations like broadcast receivers
+ * or scheduled jobs.
+ *
+ * @param service Description of the service to be stopped. The Intent must be either
+ * fully explicit (supplying a component name) or specify a specific package
+ * name it is targeted to.
+ * @param id The identifier for this notification as per
+ * {@link #notify(int, Notification) NotificationManager.notify(int, Notification)};
+ * must not be 0.
+ * @param notification The Notification to be displayed.
+ * @return If the service is being started or is already running, the
+ * {@link ComponentName} of the actual service that was started is
+ * returned; else if the service does not exist null is returned.
+ */
+ @Nullable
+ public ComponentName startServiceInForeground(Intent service,
+ int id, Notification notification) {
+ return mContext.startServiceInForeground(service, id, notification);
+ }
+
+ /**
+ * @hide like {@link #startServiceInForeground(Intent, int, Notification)}
+ * but for a specific user.
+ */
+ @Nullable
+ public ComponentName startServiceInForegroundAsUser(Intent service,
+ int id, Notification notification, UserHandle user) {
+ return mContext.startServiceInForegroundAsUser(service, id, notification, user);
+ }
+
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index af5e643..b196c64 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -35,6 +35,7 @@
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.LoadedApk;
+import android.app.Notification;
import android.app.admin.DevicePolicyManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -2517,6 +2518,17 @@
public abstract ComponentName startService(Intent service);
/**
+ * Start a service directly into the "foreground service" state. Unlike {@link #startService},
+ * this method can be used from within background operations like broadcast receivers
+ * or scheduled jobs. The API entry point for this is in NotificationManager in order to
+ * preserve appropriate public package layering.
+ * @hide
+ */
+ @Nullable
+ public abstract ComponentName startServiceInForeground(Intent service,
+ int id, Notification notification);
+
+ /**
* Request that a given application service be stopped. If the service is
* not running, nothing happens. Otherwise it is stopped. Note that calls
* to startService() are not counted -- this stops the service no matter
@@ -2547,9 +2559,18 @@
/**
* @hide like {@link #startService(Intent)} but for a specific user.
*/
+ @Nullable
public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
/**
+ * @hide like {@link #startServiceInForeground(Intent, int, Notification)}
+ * but for a specific user.
+ */
+ @Nullable
+ public abstract ComponentName startServiceInForegroundAsUser(Intent service,
+ int id, Notification notification, UserHandle user);
+
+ /**
* @hide like {@link #stopService(Intent)} but for a specific user.
*/
public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 4b6076b..c449b6a 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -20,6 +20,7 @@
import android.annotation.SystemApi;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
+import android.app.Notification;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
@@ -623,6 +624,13 @@
return mBase.startService(service);
}
+ /** @hide */
+ @Override
+ public ComponentName startServiceInForeground(Intent service,
+ int id, Notification notification) {
+ return mBase.startServiceInForeground(service, id, notification);
+ }
+
@Override
public boolean stopService(Intent name) {
return mBase.stopService(name);
@@ -636,6 +644,13 @@
/** @hide */
@Override
+ public ComponentName startServiceInForegroundAsUser(Intent service,
+ int id, Notification notification, UserHandle user) {
+ return mBase.startServiceInForegroundAsUser(service, id, notification, user);
+ }
+
+ /** @hide */
+ @Override
public boolean stopServiceAsUser(Intent name, UserHandle user) {
return mBase.stopServiceAsUser(name, user);
}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 2590a6b..bf3aa70 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -138,9 +138,8 @@
* @param userId The user under which to check.
*
* @return An {@link ApplicationInfo} containing information about the
- * package.
- * @throws NameNotFoundException if a package with the given name cannot be
- * found on the system.
+ * package, or {@code null} if no application exists with that
+ * package name.
*/
public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 168da5f..fcb4c7b 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -109,6 +109,10 @@
// background while in data-usage save mode, as read from the configuration files.
final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
+ // These are the action strings of broadcasts which are whitelisted to
+ // be delivered anonymously even to apps which target O+.
+ final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
+
// These are the package names of apps which should be in the 'always'
// URL-handling state upon factory reset.
final ArraySet<String> mLinkedApps = new ArraySet<>();
@@ -162,6 +166,10 @@
return mPermissions;
}
+ public ArraySet<String> getAllowImplicitBroadcasts() {
+ return mAllowImplicitBroadcasts;
+ }
+
public ArraySet<String> getAllowInPowerSaveExceptIdle() {
return mAllowInPowerSaveExceptIdle;
}
@@ -438,6 +446,17 @@
XmlUtils.skipCurrentTag(parser);
continue;
+ } else if ("allow-implicit-broadcast".equals(name) && allowAll) {
+ String action = parser.getAttributeValue(null, "action");
+ if (action == null) {
+ Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mAllowImplicitBroadcasts.add(action);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+
} else if ("app-link".equals(name) && allowAppConfigs) {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 6718259..b2c6840 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -18,6 +18,14 @@
########################
include $(CLEAR_VARS)
+LOCAL_MODULE := framework-sysconfig.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
LOCAL_MODULE := platform.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
@@ -31,4 +39,3 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
-
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
new file mode 100644
index 0000000..2f18de0
--- /dev/null
+++ b/data/etc/framework-sysconfig.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<!-- These are configurations that must exist on all Android devices. -->
+<config>
+
+ <!-- Broadcast actions that are currently exempted from O+ background
+ delivery restrictions. -->
+ <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" />
+ <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" />
+
+</config>
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 9f63e30..69a2c55 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1272,6 +1272,11 @@
DeviceIdleController.this.setAlarmsActive(active);
}
+ /** Is the app on any of the power save whitelists, whether system or user? */
+ public boolean isAppOnWhitelist(int appid) {
+ return DeviceIdleController.this.isAppOnWhitelistInternal(appid);
+ }
+
/**
* Returns the array of app ids whitelisted by user. Take care not to
* modify this, as it is a reference to the original copy. But the reference
@@ -1289,6 +1294,12 @@
mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
}
+ boolean isAppOnWhitelistInternal(int appid) {
+ synchronized (this) {
+ return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0;
+ }
+ }
+
int[] getPowerSaveWhitelistUserAppIds() {
synchronized (this) {
return mPowerSaveWhitelistUserAppIdArray;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 62f4f19..0834eb8 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1360,6 +1360,7 @@
}
Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Bundle data = new Bundle();
state.fillInNotifierBundle(data);
intent.putExtras(data);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7661127..7406ff8 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -305,6 +305,7 @@
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
+ int id, Notification notification,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
@@ -324,7 +325,6 @@
callerFg = true;
}
-
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
@@ -343,10 +343,11 @@
return null;
}
- if (!r.startRequested) {
+ // Non-null notification means this is a start directly into the foreground
+ if (!r.startRequested && notification == null) {
final long token = Binder.clearCallingIdentity();
try {
- // Before going further -- if this app is not allowed to run in the
+ // Before going further -- if this app is not allowed to start services in the
// background, then at this point we aren't going to let it period.
final int allowed = mAm.checkAllowBackgroundLocked(
r.appInfo.uid, r.packageName, callingPid, false);
@@ -450,7 +451,11 @@
}
}
- return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+ ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+ if (notification != null) {
+ setServiceForegroundInnerLocked(r, callingUid, notification, 0);
+ }
+ return cmp;
}
private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
@@ -595,9 +600,8 @@
for (int i=services.mServicesByName.size()-1; i>=0; i--) {
ServiceRecord service = services.mServicesByName.valueAt(i);
if (service.appInfo.uid == uid && service.startRequested) {
- if (service.appInfo.isEphemeralApp() ||
- mAm.mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
- uid, service.packageName) != AppOpsManager.MODE_ALLOWED) {
+ if (mAm.checkAllowBackgroundLocked(service.appInfo.uid, service.packageName,
+ -1, false) != ActivityManager.APP_START_MODE_NORMAL) {
if (stopping == null) {
stopping = new ArrayList<>();
stopping.add(service);
@@ -696,50 +700,55 @@
try {
ServiceRecord r = findServiceLocked(className, token, userId);
if (r != null) {
- if (id != 0) {
- if (notification == null) {
- throw new IllegalArgumentException("null notification");
- }
- if (r.foregroundId != id) {
- cancelForegroudNotificationLocked(r);
- r.foregroundId = id;
- }
- notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
- r.foregroundNoti = notification;
- r.isForeground = true;
- r.postNotification();
- if (r.app != null) {
- updateServiceForegroundLocked(r.app, true);
- }
- getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
- mAm.notifyPackageUse(r.serviceInfo.packageName,
- PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
- } else {
- if (r.isForeground) {
- r.isForeground = false;
- if (r.app != null) {
- mAm.updateLruProcessLocked(r.app, false, null);
- updateServiceForegroundLocked(r.app, true);
- }
- }
- if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
- cancelForegroudNotificationLocked(r);
- r.foregroundId = 0;
- r.foregroundNoti = null;
- } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
- r.stripForegroundServiceFlagFromNotification();
- if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
- r.foregroundId = 0;
- r.foregroundNoti = null;
- }
- }
- }
+ setServiceForegroundInnerLocked(r, userId, notification, flags);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
+ private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
+ Notification notification, int flags) {
+ if (id != 0) {
+ if (notification == null) {
+ throw new IllegalArgumentException("null notification");
+ }
+ if (r.foregroundId != id) {
+ cancelForegroudNotificationLocked(r);
+ r.foregroundId = id;
+ }
+ notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
+ r.foregroundNoti = notification;
+ r.isForeground = true;
+ r.postNotification();
+ if (r.app != null) {
+ updateServiceForegroundLocked(r.app, true);
+ }
+ getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
+ mAm.notifyPackageUse(r.serviceInfo.packageName,
+ PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
+ } else {
+ if (r.isForeground) {
+ r.isForeground = false;
+ if (r.app != null) {
+ mAm.updateLruProcessLocked(r.app, false, null);
+ updateServiceForegroundLocked(r.app, true);
+ }
+ }
+ if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
+ cancelForegroudNotificationLocked(r);
+ r.foregroundId = 0;
+ r.foregroundNoti = null;
+ } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
+ r.stripForegroundServiceFlagFromNotification();
+ if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
+ r.foregroundId = 0;
+ r.foregroundNoti = null;
+ }
+ }
+ }
+ }
+
private void cancelForegroudNotificationLocked(ServiceRecord r) {
if (r.foregroundId != 0) {
// First check to see if this app has any other active foreground services
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 43bb5ee..63187e4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -48,6 +48,7 @@
static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_ANR = false;
static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
+ static final boolean DEBUG_BACKGROUND = DEBUG_ALL || true;
static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7fd91cb..c8e1aab 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -62,6 +62,7 @@
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND;
@@ -119,6 +120,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
+import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
@@ -310,7 +312,6 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
-
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.AssistUtils;
@@ -341,6 +342,7 @@
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.Watchdog;
@@ -384,10 +386,10 @@
import java.util.concurrent.atomic.AtomicLong;
import dalvik.system.VMRuntime;
+
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
-import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -758,6 +760,18 @@
ProcessRecord mHeavyWeightProcess = null;
/**
+ * Non-persistent app uid whitelist for background restrictions
+ */
+ int[] mBackgroundUidWhitelist = new int[] {
+ Process.BLUETOOTH_UID
+ };
+
+ /**
+ * Broadcast actions that will always be deliverable to unlaunched/background apps
+ */
+ final ArraySet<String> mBackgroundLaunchBroadcasts;
+
+ /**
* All of the processes we currently have running organized by pid.
* The keys are the pid running the application.
*
@@ -2590,6 +2604,17 @@
mPermissionReviewRequired = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_permissionReviewRequired);
+ mBackgroundLaunchBroadcasts = SystemConfig.getInstance().getAllowImplicitBroadcasts();
+ if (DEBUG_BACKGROUND) {
+ StringBuilder sb = new StringBuilder(200);
+ sb.append(" ");
+ for (String a : mBackgroundLaunchBroadcasts) {
+ sb.append(' '); sb.append(a);
+ }
+ Slog.d(TAG, "Background implicit broadcasts:");
+ Slog.d(TAG, sb.toString());
+ }
+
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
@@ -4190,7 +4215,7 @@
validateUid = mValidateUids.get(item.uid);
if (validateUid == null && change != UidRecord.CHANGE_GONE
&& change != UidRecord.CHANGE_GONE_IDLE) {
- validateUid = new UidRecord(item.uid);
+ validateUid = new UidRecord(item.uid, false);
mValidateUids.put(item.uid, validateUid);
}
}
@@ -5504,6 +5529,7 @@
final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(Intent.EXTRA_UID, pkgUidF);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
@@ -6279,7 +6305,7 @@
}
UidRecord uidRec = mActiveUids.get(proc.uid);
if (uidRec == null) {
- uidRec = new UidRecord(proc.uid);
+ uidRec = new UidRecord(proc.uid, proc.persistent);
// This is the first appearance of the uid, report it now!
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Creating new process uid: " + uidRec);
@@ -8026,6 +8052,84 @@
}
}
+ // Unified app-op and target sdk check
+ boolean appRestrictedInBackgroundLocked(int uid, String packageName) {
+ if (packageName == null) {
+ packageName = mPackageManagerInt.getNameForUid(uid);
+ if (packageName == null) {
+ Slog.w(TAG, "No package known for uid " + uid);
+ return false;
+ }
+ }
+
+ // !!! TODO: cache the package/versionCode lookups to fast path this
+ ApplicationInfo app = getPackageManagerInternalLocked().getApplicationInfo(packageName,
+ UserHandle.getUserId(uid));
+ if (app != null) {
+ // Apps that target O+ are always subject to background check
+ if (app.targetSdkVersion >= Build.VERSION_CODES.O) {
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
+ }
+ return true;
+ }
+ // ...and legacy apps get an AppOp check
+ int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
+ uid, packageName);
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
+ }
+ return (appop != AppOpsManager.MODE_ALLOWED);
+ } else {
+ Slog.w(TAG, "Unknown app " + packageName + " / " + uid);
+ }
+ return false;
+ }
+
+ // Service launch is available to apps with run-in-background exemptions but
+ // some other background operations are not. If we're doing a check
+ // of service-launch policy, allow those callers to proceed unrestricted.
+ boolean appServicesRestrictedInBackgroundLocked(int uid, String packageName) {
+ if (packageName == null) {
+ packageName = mPackageManagerInt.getNameForUid(uid);
+ if (packageName == null) {
+ Slog.w(TAG, "No package known for uid " + uid);
+ return false;
+ }
+ }
+
+ // Persistent app? NB: expects that persistent uids are always active.
+ final UidRecord uidRec = mActiveUids.get(uid);
+ if (uidRec != null && uidRec.persistent) {
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "App " + uid + "/" + packageName
+ + " is persistent; not restricted in background");
+ }
+ return false;
+ }
+
+ // Non-persistent but background whitelisted?
+ if (uidOnBackgroundWhitelist(uid)) {
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "App " + uid + "/" + packageName
+ + " on background whitelist; not restricted in background");
+ }
+ return false;
+ }
+
+ // Is this app on the battery whitelist?
+ if (mLocalDeviceIdleController.isAppOnWhitelist(UserHandle.getAppId(uid))) {
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "App " + uid + "/" + packageName
+ + " on idle whitelist; not restricted in background");
+ }
+ return false;
+ }
+
+ // None of the service-policy criteria apply, so we apply the common criteria
+ return appRestrictedInBackgroundLocked(uid, packageName);
+ }
+
int checkAllowBackgroundLocked(int uid, String packageName, int callingPid,
boolean alwaysRestrict) {
UidRecord uidRec = mActiveUids.get(uid);
@@ -8054,8 +8158,13 @@
return ActivityManager.APP_START_MODE_NORMAL;
}
}
- if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid,
- packageName) != AppOpsManager.MODE_ALLOWED) {
+ final boolean restricted = (alwaysRestrict)
+ ? appRestrictedInBackgroundLocked(uid, packageName)
+ : appServicesRestrictedInBackgroundLocked(uid, packageName);
+ if (restricted) {
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "App " + uid + "/" + packageName + " restricted in background");
+ }
return ActivityManager.APP_START_MODE_DELAYED;
}
}
@@ -11651,6 +11760,16 @@
return r;
}
+ private boolean uidOnBackgroundWhitelist(final int uid) {
+ final int N = mBackgroundUidWhitelist.length;
+ for (int i = 0; i < N; i++) {
+ if (uid == mBackgroundUidWhitelist[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
String abiOverride) {
ProcessRecord app;
@@ -17284,7 +17403,8 @@
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType, String callingPackage, int userId)
+ String resolvedType, int id, Notification notification,
+ String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
@@ -17303,7 +17423,8 @@
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
- resolvedType, callingPid, callingUid, callingPackage, userId);
+ resolvedType, id, notification,
+ callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -17317,7 +17438,7 @@
"startServiceInPackage: " + service + " type=" + resolvedType);
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(null, service,
- resolvedType, -1, uid, callingPackage, userId);
+ resolvedType, 0, null, -1, uid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -18176,6 +18297,13 @@
}
if (action != null) {
+ if (mBackgroundLaunchBroadcasts.contains(action)) {
+ if (DEBUG_BACKGROUND) {
+ Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
+ }
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ }
+
switch (action) {
case Intent.ACTION_UID_REMOVED:
case Intent.ACTION_PACKAGE_REMOVED:
@@ -19300,7 +19428,8 @@
UserHandle.USER_ALL);
if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
if (initLocale || !mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 29a4781..414488e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -490,7 +490,7 @@
pw.println("Starting service: " + intent);
pw.flush();
ComponentName cn = mInterface.startService(null, intent, intent.getType(),
- SHELL_PACKAGE_NAME, mUserId);
+ -1, null, SHELL_PACKAGE_NAME, mUserId);
if (cn == null) {
err.println("Error: Not found; no service started.");
return -1;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 8104a43..61e555b 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1157,8 +1157,7 @@
if (!skip) {
final int allowed = mService.checkAllowBackgroundLocked(
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1,
- true);
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1, true);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// We won't allow this receiver to be launched if the app has been
// completely disabled from launches, or it was not explicitly sent
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index d1a15bd..4ebd068 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -26,6 +26,7 @@
*/
public final class UidRecord {
final int uid;
+ final boolean persistent;
int curProcState;
int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
long lastBackgroundTime;
@@ -49,8 +50,9 @@
ChangeItem pendingChange;
- public UidRecord(int _uid) {
+ public UidRecord(int _uid, boolean _persist) {
uid = _uid;
+ persistent = _persist;
reset();
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 71ebad9..31b7ca7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -414,7 +414,8 @@
if (userId != UserHandle.USER_SYSTEM) {
Slog.d(TAG, "Initializing user #" + userId);
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mInjector.broadcastIntentLocked(intent, null,
new IIntentReceiver.Stub() {
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index af1e007..c793f49 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -80,7 +80,6 @@
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
-
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
@@ -5965,7 +5964,7 @@
int status = (int)(packedStatus >> 32);
int linkGeneration = (int)(packedStatus & 0xFFFFFFFF);
if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
- if (DEBUG_DOMAIN_VERIFICATION) {
+ if (DEBUG_DOMAIN_VERIFICATION || debug) {
Slog.i(TAG, " + always: " + info.activityInfo.packageName
+ " : linkgen=" + linkGeneration);
}
@@ -5974,18 +5973,18 @@
info.preferredOrder = linkGeneration;
alwaysList.add(info);
} else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
- if (DEBUG_DOMAIN_VERIFICATION) {
+ if (DEBUG_DOMAIN_VERIFICATION || debug) {
Slog.i(TAG, " + never: " + info.activityInfo.packageName);
}
neverList.add(info);
} else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
- if (DEBUG_DOMAIN_VERIFICATION) {
+ if (DEBUG_DOMAIN_VERIFICATION || debug) {
Slog.i(TAG, " + always-ask: " + info.activityInfo.packageName);
}
alwaysAskList.add(info);
} else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED ||
status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK) {
- if (DEBUG_DOMAIN_VERIFICATION) {
+ if (DEBUG_DOMAIN_VERIFICATION || debug) {
Slog.i(TAG, " + ask: " + info.activityInfo.packageName);
}
undefinedList.add(info);
@@ -12143,7 +12142,7 @@
IActivityManager am = ActivityManager.getService();
if (am != null) {
try {
- am.startService(null, intent, null, mContext.getOpPackageName(),
+ am.startService(null, intent, null, -1, null, mContext.getOpPackageName(),
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
}
@@ -16627,7 +16626,8 @@
extras, 0, null, null, removedUsers);
if (dataRemoved && !isRemovedPackageSystemUpdate) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
- removedPackage, extras, 0, null, null, removedUsers);
+ removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+ null, null, removedUsers);
}
}
if (removedAppId >= 0) {
@@ -19581,7 +19581,8 @@
count = 0;
for (PackageSetting ps : allPackageSettings) {
final long status = ps.getDomainVerificationStatusForUser(userId);
- if (status >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+ if (status >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED
+ && !DEBUG_DOMAIN_VERIFICATION) {
continue;
}
pw.println(prefix + "Package: " + ps.name);
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index 90c711a..a3837b2 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -338,9 +338,11 @@
mTotalMemory = (long)mDataFileStats.getBlockCount() *
mDataFileStats.getBlockSize();
mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
- mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
- mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 7f182a4..4aff3d54 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -556,7 +556,9 @@
private void sendPortChangedBroadcastLocked(PortInfo portInfo) {
final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.addFlags(
+ Intent.FLAG_RECEIVER_FOREGROUND |
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(UsbManager.EXTRA_PORT, portInfo.mUsbPort);
intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index e03a14f..2e99b6e 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -971,7 +971,9 @@
public void accessoryAttached(UsbAccessory accessory) {
Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
ArrayList<ResolveInfo> matches;
String defaultPackage = null;
@@ -1364,7 +1366,9 @@
private static Intent createDeviceAttachedIntent(UsbDevice device) {
Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
return intent;
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 24d5f09..7a55be4 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -182,6 +182,7 @@
}
Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
if (DEBUG) {
@@ -204,6 +205,7 @@
}
Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index bcc68b3..b6e701e 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -19,6 +19,7 @@
import android.annotation.SystemApi;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
+import android.app.Notification;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -513,6 +514,12 @@
}
@Override
+ public ComponentName startServiceInForeground(Intent service,
+ int id, Notification notification) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public boolean stopService(Intent service) {
throw new UnsupportedOperationException();
}
@@ -525,6 +532,13 @@
/** @hide */
@Override
+ public ComponentName startServiceInForegroundAsUser(Intent service,
+ int id, Notification notification, UserHandle user) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
+ @Override
public boolean stopServiceAsUser(Intent service, UserHandle user) {
throw new UnsupportedOperationException();
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 663e56d..68680d5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -40,6 +40,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -1820,6 +1821,13 @@
}
@Override
+ public ComponentName startServiceInForeground(Intent service,
+ int id, Notification notification) {
+ // pass
+ return null;
+ }
+
+ @Override
public boolean stopService(Intent arg0) {
// pass
return false;
@@ -1832,6 +1840,13 @@
}
@Override
+ public ComponentName startServiceInForegroundAsUser(Intent service,
+ int id, Notification notification, UserHandle user) {
+ // pass
+ return null;
+ }
+
+ @Override
public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
// pass
return false;