Merge "API refactor: context.startForegroundService()" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
60e0c19505
@@ -5586,7 +5586,7 @@ package android.app {
|
||||
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 deprecated 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";
|
||||
@@ -5641,6 +5641,7 @@ package android.app {
|
||||
method public java.lang.String getCreatorPackage();
|
||||
method public int getCreatorUid();
|
||||
method public android.os.UserHandle getCreatorUserHandle();
|
||||
method public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int);
|
||||
method public android.content.IntentSender getIntentSender();
|
||||
method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
|
||||
method public deprecated java.lang.String getTargetPackage();
|
||||
@@ -8858,6 +8859,7 @@ package android.content {
|
||||
method public abstract void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public abstract void startActivity(android.content.Intent);
|
||||
method public abstract void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public abstract android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public abstract boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
|
||||
method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
|
||||
@@ -9049,6 +9051,7 @@ package android.content {
|
||||
method public void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
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;
|
||||
@@ -40679,6 +40682,7 @@ package android.test.mock {
|
||||
method public void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
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;
|
||||
|
||||
@@ -5780,7 +5780,7 @@ package android.app {
|
||||
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 deprecated 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";
|
||||
@@ -5835,6 +5835,7 @@ package android.app {
|
||||
method public java.lang.String getCreatorPackage();
|
||||
method public int getCreatorUid();
|
||||
method public android.os.UserHandle getCreatorUserHandle();
|
||||
method public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int);
|
||||
method public android.content.IntentSender getIntentSender();
|
||||
method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
|
||||
method public deprecated java.lang.String getTargetPackage();
|
||||
@@ -9353,6 +9354,7 @@ package android.content {
|
||||
method public abstract void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public abstract void startActivity(android.content.Intent);
|
||||
method public abstract void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public abstract android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public abstract boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
|
||||
method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
|
||||
@@ -9558,6 +9560,7 @@ package android.content {
|
||||
method public void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
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;
|
||||
@@ -44117,6 +44120,7 @@ package android.test.mock {
|
||||
method public void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
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;
|
||||
|
||||
@@ -5599,7 +5599,7 @@ package android.app {
|
||||
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 deprecated 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";
|
||||
@@ -5654,6 +5654,7 @@ package android.app {
|
||||
method public java.lang.String getCreatorPackage();
|
||||
method public int getCreatorUid();
|
||||
method public android.os.UserHandle getCreatorUserHandle();
|
||||
method public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int);
|
||||
method public android.content.IntentSender getIntentSender();
|
||||
method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
|
||||
method public deprecated java.lang.String getTargetPackage();
|
||||
@@ -8890,6 +8891,7 @@ package android.content {
|
||||
method public abstract void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public abstract void startActivity(android.content.Intent);
|
||||
method public abstract void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public abstract android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public abstract boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
|
||||
method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
|
||||
@@ -9082,6 +9084,7 @@ package android.content {
|
||||
method public void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
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;
|
||||
@@ -40883,6 +40886,7 @@ package android.test.mock {
|
||||
method public void startActivities(android.content.Intent[], android.os.Bundle);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivity(android.content.Intent, android.os.Bundle);
|
||||
method public android.content.ComponentName startForegroundService(android.content.Intent);
|
||||
method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
|
||||
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;
|
||||
|
||||
@@ -405,6 +405,13 @@ public class ActivityManager {
|
||||
*/
|
||||
public static final int INTENT_SENDER_SERVICE = 4;
|
||||
|
||||
/**
|
||||
* Type for IActivityManaqer.getIntentSender: this PendingIntent is
|
||||
* for a startForegroundService operation.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INTENT_SENDER_FOREGROUND_SERVICE = 5;
|
||||
|
||||
/** @hide User operation call: success! */
|
||||
public static final int USER_OP_SUCCESS = 0;
|
||||
|
||||
|
||||
@@ -1447,14 +1447,21 @@ class ContextImpl extends Context {
|
||||
@Override
|
||||
public ComponentName startService(Intent service) {
|
||||
warnIfCallingFromSystemProcess();
|
||||
return startServiceCommon(service, -1, null, mUser);
|
||||
return startServiceCommon(service, -1, null, false, mUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startForegroundService(Intent service) {
|
||||
warnIfCallingFromSystemProcess();
|
||||
return startServiceCommon(service, -1, null, true, mUser);
|
||||
}
|
||||
|
||||
// STOPSHIP: remove when NotificationManager.startServiceInForeground() is retired
|
||||
@Override
|
||||
public ComponentName startServiceInForeground(Intent service,
|
||||
int id, Notification notification) {
|
||||
warnIfCallingFromSystemProcess();
|
||||
return startServiceCommon(service, id, notification, mUser);
|
||||
return startServiceCommon(service, id, notification, false, mUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1465,24 +1472,30 @@ class ContextImpl extends Context {
|
||||
|
||||
@Override
|
||||
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
|
||||
return startServiceCommon(service, -1, null, user);
|
||||
return startServiceCommon(service, -1, null, false, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
|
||||
return startServiceCommon(service, -1, null, true, user);
|
||||
}
|
||||
|
||||
// STOPSHIP: remove when NotificationManager.startServiceInForeground() is retired
|
||||
@Override
|
||||
public ComponentName startServiceInForegroundAsUser(Intent service,
|
||||
int id, Notification notification, UserHandle user) {
|
||||
return startServiceCommon(service, id, notification, user);
|
||||
return startServiceCommon(service, id, notification, false, user);
|
||||
}
|
||||
|
||||
private ComponentName startServiceCommon(Intent service, int id, Notification notification,
|
||||
UserHandle user) {
|
||||
boolean requireForeground, UserHandle user) {
|
||||
try {
|
||||
validateServiceIntent(service);
|
||||
service.prepareToLeaveProcess(this);
|
||||
ComponentName cn = ActivityManager.getService().startService(
|
||||
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
|
||||
getContentResolver()), id, notification, getOpPackageName(),
|
||||
user.getIdentifier());
|
||||
getContentResolver()), id, notification, requireForeground,
|
||||
getOpPackageName(), user.getIdentifier());
|
||||
if (cn != null) {
|
||||
if (cn.getPackageName().equals("!")) {
|
||||
throw new SecurityException(
|
||||
|
||||
@@ -130,7 +130,7 @@ interface IActivityManager {
|
||||
PendingIntent getRunningServiceControlPanel(in ComponentName service);
|
||||
ComponentName startService(in IApplicationThread caller, in Intent service,
|
||||
in String resolvedType, int id, in Notification notification,
|
||||
in String callingPackage, int userId);
|
||||
boolean requireForeground, 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,
|
||||
|
||||
@@ -1171,8 +1171,11 @@ public class NotificationManager
|
||||
* @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.
|
||||
*
|
||||
* @deprecated STOPSHIP transition away from this for O
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public ComponentName startServiceInForeground(Intent service,
|
||||
int id, Notification notification) {
|
||||
return mContext.startServiceInForeground(service, id, notification);
|
||||
|
||||
@@ -596,6 +596,42 @@ public final class PendingIntent implements Parcelable {
|
||||
*/
|
||||
public static PendingIntent getService(Context context, int requestCode,
|
||||
@NonNull Intent intent, @Flags int flags) {
|
||||
return buildServicePendingIntent(context, requestCode, intent, flags,
|
||||
ActivityManager.INTENT_SENDER_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a PendingIntent that will start a foreground service, like calling
|
||||
* {@link Context#startService Context.startForegroundService()}. The start
|
||||
* arguments given to the service will come from the extras of the Intent.
|
||||
*
|
||||
* <p class="note">For security reasons, the {@link android.content.Intent}
|
||||
* you supply here should almost always be an <em>explicit intent</em>,
|
||||
* that is specify an explicit component to be delivered to through
|
||||
* {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
|
||||
*
|
||||
* @param context The Context in which this PendingIntent should start
|
||||
* the service.
|
||||
* @param requestCode Private request code for the sender
|
||||
* @param intent An Intent describing the service to be started.
|
||||
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
|
||||
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
|
||||
* {@link #FLAG_IMMUTABLE} or any of the flags as supported by
|
||||
* {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
|
||||
* of the intent that can be supplied when the actual send happens.
|
||||
*
|
||||
* @return Returns an existing or new PendingIntent matching the given
|
||||
* parameters. May return null only if {@link #FLAG_NO_CREATE} has been
|
||||
* supplied.
|
||||
*/
|
||||
public static PendingIntent getForegroundService(Context context, int requestCode,
|
||||
@NonNull Intent intent, @Flags int flags) {
|
||||
return buildServicePendingIntent(context, requestCode, intent, flags,
|
||||
ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE);
|
||||
}
|
||||
|
||||
private static PendingIntent buildServicePendingIntent(Context context, int requestCode,
|
||||
Intent intent, int flags, int serviceKind) {
|
||||
String packageName = context.getPackageName();
|
||||
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
|
||||
context.getContentResolver()) : null;
|
||||
@@ -603,7 +639,7 @@ public final class PendingIntent implements Parcelable {
|
||||
intent.prepareToLeaveProcess(context);
|
||||
IIntentSender target =
|
||||
ActivityManager.getService().getIntentSender(
|
||||
ActivityManager.INTENT_SENDER_SERVICE, packageName,
|
||||
serviceKind, packageName,
|
||||
null, null, requestCode, new Intent[] { intent },
|
||||
resolvedType != null ? new String[] { resolvedType } : null,
|
||||
flags, null, UserHandle.myUserId());
|
||||
|
||||
@@ -2576,7 +2576,7 @@ public abstract class Context {
|
||||
* {@link ComponentName} of the actual service that was started is
|
||||
* returned; else if the service does not exist null is returned.
|
||||
*
|
||||
* @throws SecurityException If the caller does not permission to access the service
|
||||
* @throws SecurityException If the caller does not have permission to access the service
|
||||
* or the service can not be found.
|
||||
* @throws IllegalStateException If the application is in a state where the service
|
||||
* can not be started (such as not in the foreground in a state when services are allowed).
|
||||
@@ -2587,12 +2587,48 @@ public abstract class Context {
|
||||
@Nullable
|
||||
public abstract ComponentName startService(Intent service);
|
||||
|
||||
/**
|
||||
* Similar to {@link #startService(Intent)}, but with an implicit promise that the
|
||||
* Service will call {@link android.app.Service#startForeground(int, Notification)
|
||||
* startForeground(int, Notification)} once it begins running. The service is given
|
||||
* an amount of time comparable to the ANR interval to do this, otherwise the system
|
||||
* will automatically stop the service and declare the app ANR.
|
||||
*
|
||||
* <p>Unlike the ordinary {@link #startService(Intent)}, this method can be used
|
||||
* at any time, regardless of whether the app hosting the service is in a foreground
|
||||
* state.
|
||||
*
|
||||
* @param service Identifies the service to be started. The Intent must be
|
||||
* fully explicit (supplying a component name). Additional values
|
||||
* may be included in the Intent extras to supply arguments along with
|
||||
* this specific start call.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @throws SecurityException If the caller does not have permission to access the service
|
||||
* or the service can not be found.
|
||||
*
|
||||
* @see #stopService
|
||||
* @see android.app.Service#startForeground(int, Notification)
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ComponentName startForegroundService(Intent service);
|
||||
|
||||
/**
|
||||
* @hide like {@link #startForegroundService(Intent)} but for a specific user.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ComponentName startForegroundServiceAsUser(Intent service, UserHandle user);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @deprecated STOPSHIP remove in favor of two-step startForegroundService() + startForeground()
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ComponentName startServiceInForeground(Intent service,
|
||||
@@ -2620,7 +2656,7 @@ public abstract class Context {
|
||||
* @return If there is a service matching the given Intent that is already
|
||||
* running, then it is stopped and {@code true} is returned; else {@code false} is returned.
|
||||
*
|
||||
* @throws SecurityException If the caller does not permission to access the service
|
||||
* @throws SecurityException If the caller does not have permission to access the service
|
||||
* or the service can not be found.
|
||||
* @throws IllegalStateException If the application is in a state where the service
|
||||
* can not be started (such as not in the foreground in a state when services are allowed).
|
||||
@@ -2638,7 +2674,9 @@ public abstract class Context {
|
||||
/**
|
||||
* @hide like {@link #startServiceInForeground(Intent, int, Notification)}
|
||||
* but for a specific user.
|
||||
* @deprecated STOPSHIP remove when trial API is turned off
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public abstract ComponentName startServiceInForegroundAsUser(Intent service,
|
||||
int id, Notification notification, UserHandle user);
|
||||
@@ -2685,7 +2723,7 @@ public abstract class Context {
|
||||
* {@code false} is returned if the connection is not made so you will not
|
||||
* receive the service object.
|
||||
*
|
||||
* @throws SecurityException If the caller does not permission to access the service
|
||||
* @throws SecurityException If the caller does not have permission to access the service
|
||||
* or the service can not be found.
|
||||
*
|
||||
* @see #unbindService
|
||||
|
||||
@@ -644,7 +644,12 @@ public class ContextWrapper extends Context {
|
||||
return mBase.startService(service);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public ComponentName startForegroundService(Intent service) {
|
||||
return mBase.startForegroundService(service);
|
||||
}
|
||||
|
||||
/** @hide STOPSHIP remove when trial API is turned down */
|
||||
@Override
|
||||
public ComponentName startServiceInForeground(Intent service,
|
||||
int id, Notification notification) {
|
||||
@@ -664,6 +669,12 @@ public class ContextWrapper extends Context {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
|
||||
return mBase.startForegroundServiceAsUser(service, user);
|
||||
}
|
||||
|
||||
/** @hide STOPSHIP removed when trial API is turned down */
|
||||
@Override
|
||||
public ComponentName startServiceInForegroundAsUser(Intent service,
|
||||
int id, Notification notification, UserHandle user) {
|
||||
return mBase.startServiceInForegroundAsUser(service, id, notification, user);
|
||||
|
||||
@@ -36,8 +36,8 @@ public class ContextThemeWrapper extends ContextWrapper {
|
||||
|
||||
/**
|
||||
* Creates a new context wrapper with no theme and no base context.
|
||||
* <p>
|
||||
* <stong>Note:</strong> A base context <strong>must</strong> be attached
|
||||
* <p class="note">
|
||||
* <strong>Note:</strong> A base context <strong>must</strong> be attached
|
||||
* using {@link #attachBaseContext(Context)} before calling any other
|
||||
* method on the newly constructed context wrapper.
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.server.am;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.*;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -96,6 +95,10 @@ public final class ActiveServices {
|
||||
// How long we wait for a service to finish executing.
|
||||
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
|
||||
|
||||
// How long the startForegroundService() grace period is to get around to
|
||||
// calling startForeground() before we ANR + stop it.
|
||||
static final int SERVICE_START_FOREGROUND_TIMEOUT = 5*1000;
|
||||
|
||||
// How long a service needs to be running until restarting its process
|
||||
// is no longer considered to be a relaunch of the service.
|
||||
static final int SERVICE_RESTART_DURATION = 1*1000;
|
||||
@@ -307,8 +310,8 @@ public final class ActiveServices {
|
||||
}
|
||||
|
||||
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
|
||||
int id, Notification notification,
|
||||
int callingPid, int callingUid, String callingPackage, final int userId)
|
||||
int id, Notification notification, int callingPid, int callingUid,
|
||||
boolean fgRequired, String callingPackage, final int userId)
|
||||
throws TransactionTooLargeException {
|
||||
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
|
||||
+ " type=" + resolvedType + " args=" + service.getExtras());
|
||||
@@ -345,8 +348,9 @@ public final class ActiveServices {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Non-null notification means this is a start directly into the foreground
|
||||
if (!r.startRequested && notification == null) {
|
||||
// If this isn't a direct-to-foreground start, check our ability to kick off an
|
||||
// arbitrary service
|
||||
if (!r.startRequested && !fgRequired) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
// Before going further -- if this app is not allowed to start services in the
|
||||
@@ -392,12 +396,13 @@ public final class ActiveServices {
|
||||
r.lastActivity = SystemClock.uptimeMillis();
|
||||
r.startRequested = true;
|
||||
r.delayedStop = false;
|
||||
r.fgRequired = fgRequired;
|
||||
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
|
||||
service, neededGrants));
|
||||
|
||||
final ServiceMap smap = getServiceMapLocked(r.userId);
|
||||
boolean addToStarting = false;
|
||||
if (!callerFg && r.app == null
|
||||
if (!callerFg && !fgRequired && r.app == null
|
||||
&& mAm.mUserController.hasStartedUserState(r.userId)) {
|
||||
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
|
||||
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
|
||||
@@ -449,9 +454,9 @@ public final class ActiveServices {
|
||||
Slog.v(TAG_SERVICE, sb.toString());
|
||||
}
|
||||
} else if (DEBUG_DELAYED_STARTS) {
|
||||
if (callerFg) {
|
||||
if (callerFg || fgRequired) {
|
||||
Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid="
|
||||
+ callingUid + " pid=" + callingPid + "): " + r);
|
||||
+ callingUid + " pid=" + callingPid + " fgRequired=" + fgRequired + "): " + r);
|
||||
} else if (r.app != null) {
|
||||
Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r);
|
||||
} else {
|
||||
@@ -461,6 +466,7 @@ public final class ActiveServices {
|
||||
}
|
||||
|
||||
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
|
||||
// STOPSHIP deprecated; remove when NotificationManager.startServiceInForeground is retired
|
||||
if (notification != null) {
|
||||
setServiceForegroundInnerLocked(r, id, notification, 0);
|
||||
}
|
||||
@@ -540,7 +546,7 @@ public final class ActiveServices {
|
||||
if (first) {
|
||||
smap.rescheduleDelayedStartsLocked();
|
||||
}
|
||||
} else if (callerFg) {
|
||||
} else if (callerFg || r.fgRequired) {
|
||||
smap.ensureNotStartingBackgroundLocked(r);
|
||||
}
|
||||
|
||||
@@ -756,8 +762,17 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r.fgRequired) {
|
||||
if (DEBUG_BACKGROUND_CHECK) {
|
||||
Slog.i(TAG, "Service called startForeground() as required: " + r);
|
||||
}
|
||||
r.fgRequired = false;
|
||||
r.fgWaiting = false;
|
||||
mAm.mHandler.removeMessages(
|
||||
ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
|
||||
}
|
||||
if (r.foregroundId != id) {
|
||||
cancelForegroudNotificationLocked(r);
|
||||
cancelForegroundNotificationLocked(r);
|
||||
r.foregroundId = id;
|
||||
}
|
||||
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
|
||||
@@ -779,7 +794,7 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
|
||||
cancelForegroudNotificationLocked(r);
|
||||
cancelForegroundNotificationLocked(r);
|
||||
r.foregroundId = 0;
|
||||
r.foregroundNoti = null;
|
||||
} else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
@@ -792,7 +807,7 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelForegroudNotificationLocked(ServiceRecord r) {
|
||||
private void cancelForegroundNotificationLocked(ServiceRecord r) {
|
||||
if (r.foregroundId != 0) {
|
||||
// First check to see if this app has any other active foreground services
|
||||
// with the same notification ID. If so, we shouldn't actually cancel it,
|
||||
@@ -1631,7 +1646,7 @@ public final class ActiveServices {
|
||||
r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
|
||||
}
|
||||
|
||||
cancelForegroudNotificationLocked(r);
|
||||
cancelForegroundNotificationLocked(r);
|
||||
|
||||
mAm.mHandler.removeCallbacks(r.restarter);
|
||||
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
|
||||
@@ -1718,7 +1733,9 @@ public final class ActiveServices {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);
|
||||
if (DEBUG_SERVICE) {
|
||||
Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent + " fg=" + r.fgRequired);
|
||||
}
|
||||
|
||||
// We are now bringing the service up, so no longer in the
|
||||
// restarting state.
|
||||
@@ -1944,8 +1961,10 @@ public final class ActiveServices {
|
||||
ServiceRecord.StartItem si = null;
|
||||
try {
|
||||
si = r.pendingStarts.remove(0);
|
||||
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Sending arguments to: "
|
||||
+ r + " " + r.intent + " args=" + si.intent);
|
||||
if (DEBUG_SERVICE) {
|
||||
Slog.v(TAG_SERVICE, "Sending arguments to: "
|
||||
+ r + " " + r.intent + " args=" + si.intent);
|
||||
}
|
||||
if (si.intent == null && N > 1) {
|
||||
// If somehow we got a dummy null intent in the middle,
|
||||
// then skip it. DO NOT skip a null intent when it is
|
||||
@@ -1966,6 +1985,19 @@ public final class ActiveServices {
|
||||
oomAdjusted = true;
|
||||
mAm.updateOomAdjLocked(r.app);
|
||||
}
|
||||
if (r.fgRequired && !r.fgWaiting) {
|
||||
if (!r.isForeground) {
|
||||
if (DEBUG_BACKGROUND_CHECK) {
|
||||
Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);
|
||||
}
|
||||
scheduleServiceForegroundTransitionTimeoutLocked(r);
|
||||
} else {
|
||||
if (DEBUG_BACKGROUND_CHECK) {
|
||||
Slog.i(TAG, "Service already foreground; no new timeout: " + r);
|
||||
}
|
||||
r.fgRequired = false;
|
||||
}
|
||||
}
|
||||
int flags = 0;
|
||||
if (si.deliveryCount > 1) {
|
||||
flags |= Service.START_FLAG_RETRY;
|
||||
@@ -2101,7 +2133,7 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
cancelForegroudNotificationLocked(r);
|
||||
cancelForegroundNotificationLocked(r);
|
||||
r.isForeground = false;
|
||||
r.foregroundId = 0;
|
||||
r.foregroundNoti = null;
|
||||
@@ -2925,23 +2957,53 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
void serviceForegroundTimeout(ServiceRecord r) {
|
||||
ProcessRecord app;
|
||||
synchronized (mAm) {
|
||||
if (!r.fgRequired) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_BACKGROUND_CHECK) {
|
||||
Slog.i(TAG, "Service foreground-required timeout for " + r);
|
||||
}
|
||||
app = r.app;
|
||||
r.fgWaiting = false;
|
||||
stopServiceLocked(r);
|
||||
}
|
||||
|
||||
if (app != null) {
|
||||
mAm.mAppErrors.appNotResponding(app, null, null, false,
|
||||
"Context.startForegroundService() did not then call Service.startForeground()");
|
||||
}
|
||||
}
|
||||
|
||||
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
|
||||
if (proc.executingServices.size() == 0 || proc.thread == null) {
|
||||
return;
|
||||
}
|
||||
long now = SystemClock.uptimeMillis();
|
||||
Message msg = mAm.mHandler.obtainMessage(
|
||||
ActivityManagerService.SERVICE_TIMEOUT_MSG);
|
||||
msg.obj = proc;
|
||||
mAm.mHandler.sendMessageAtTime(msg,
|
||||
proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
|
||||
mAm.mHandler.sendMessageDelayed(msg,
|
||||
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
|
||||
}
|
||||
|
||||
void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
|
||||
if (r.app.executingServices.size() == 0 || r.app.thread == null) {
|
||||
return;
|
||||
}
|
||||
Message msg = mAm.mHandler.obtainMessage(
|
||||
ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
|
||||
msg.obj = r;
|
||||
r.fgWaiting = true;
|
||||
mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT);
|
||||
}
|
||||
|
||||
final class ServiceDumper {
|
||||
private final FileDescriptor fd;
|
||||
private final PrintWriter pw;
|
||||
private final String[] args;
|
||||
private final int opti;
|
||||
private final boolean dumpAll;
|
||||
private final String dumpPackage;
|
||||
private final ItemMatcher matcher;
|
||||
@@ -2962,7 +3024,6 @@ public final class ActiveServices {
|
||||
this.fd = fd;
|
||||
this.pw = pw;
|
||||
this.args = args;
|
||||
this.opti = opti;
|
||||
this.dumpAll = dumpAll;
|
||||
this.dumpPackage = dumpPackage;
|
||||
matcher = new ItemMatcher();
|
||||
|
||||
@@ -1726,6 +1726,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 63;
|
||||
static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 64;
|
||||
static final int NOTIFY_VR_SLEEPING_MSG = 65;
|
||||
static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
|
||||
static final int START_USER_SWITCH_FG_MSG = 712;
|
||||
|
||||
static final int FIRST_ACTIVITY_STACK_MSG = 100;
|
||||
@@ -1991,6 +1992,9 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
mServices.serviceTimeout((ProcessRecord)msg.obj);
|
||||
} break;
|
||||
case SERVICE_FOREGROUND_TIMEOUT_MSG: {
|
||||
mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
|
||||
} break;
|
||||
case UPDATE_TIME_ZONE: {
|
||||
synchronized (ActivityManagerService.this) {
|
||||
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
|
||||
@@ -17898,7 +17902,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public ComponentName startService(IApplicationThread caller, Intent service,
|
||||
String resolvedType, int id, Notification notification,
|
||||
String resolvedType, int id, Notification notification, boolean requireForeground,
|
||||
String callingPackage, int userId)
|
||||
throws TransactionTooLargeException {
|
||||
enforceNotIsolatedCaller("startService");
|
||||
@@ -17912,28 +17916,28 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
|
||||
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
|
||||
"startService: " + service + " type=" + resolvedType);
|
||||
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
|
||||
synchronized(this) {
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
ComponentName res = mServices.startServiceLocked(caller, service,
|
||||
resolvedType, id, notification,
|
||||
callingPid, callingUid, callingPackage, userId);
|
||||
resolvedType, id, notification, callingPid, callingUid,
|
||||
requireForeground, callingPackage, userId);
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
|
||||
String callingPackage, int userId)
|
||||
boolean fgRequired, String callingPackage, int userId)
|
||||
throws TransactionTooLargeException {
|
||||
synchronized(this) {
|
||||
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
|
||||
"startServiceInPackage: " + service + " type=" + resolvedType);
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
ComponentName res = mServices.startServiceLocked(null, service,
|
||||
resolvedType, 0, null, -1, uid, callingPackage, userId);
|
||||
resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId);
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
pw.println("Starting service: " + intent);
|
||||
pw.flush();
|
||||
ComponentName cn = mInterface.startService(null, intent, intent.getType(),
|
||||
-1, null, SHELL_PACKAGE_NAME, mUserId);
|
||||
-1, null, false, SHELL_PACKAGE_NAME, mUserId);
|
||||
if (cn == null) {
|
||||
err.println("Error: Not found; no service started.");
|
||||
return -1;
|
||||
|
||||
@@ -175,6 +175,8 @@ final class PendingIntentRecord extends IIntentSender.Stub {
|
||||
return "broadcastIntent";
|
||||
case ActivityManager.INTENT_SENDER_SERVICE:
|
||||
return "startService";
|
||||
case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
|
||||
return "startForegroundService";
|
||||
case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
|
||||
return "activityResult";
|
||||
}
|
||||
@@ -318,9 +320,11 @@ final class PendingIntentRecord extends IIntentSender.Stub {
|
||||
}
|
||||
break;
|
||||
case ActivityManager.INTENT_SENDER_SERVICE:
|
||||
case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
|
||||
try {
|
||||
owner.startServiceInPackage(uid, finalIntent,
|
||||
resolvedType, key.packageName, userId);
|
||||
owner.startServiceInPackage(uid, finalIntent, resolvedType,
|
||||
key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
|
||||
key.packageName, userId);
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "Unable to send startService intent", e);
|
||||
} catch (TransactionTooLargeException e) {
|
||||
|
||||
@@ -92,6 +92,8 @@ final class ServiceRecord extends Binder {
|
||||
ServiceState restartTracker; // tracking service restart
|
||||
boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
|
||||
boolean delayed; // are we waiting to start this service in the background?
|
||||
boolean fgRequired; // is the service required to go foreground after starting?
|
||||
boolean fgWaiting; // is a timeout for going foreground already scheduled?
|
||||
boolean isForeground; // is service currently in foreground mode?
|
||||
int foregroundId; // Notification ID of last foreground req.
|
||||
Notification foregroundNoti; // Notification record of foreground state.
|
||||
|
||||
@@ -12968,7 +12968,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
IActivityManager am = ActivityManager.getService();
|
||||
if (am != null) {
|
||||
try {
|
||||
am.startService(null, intent, null, -1, null, mContext.getOpPackageName(),
|
||||
am.startService(null, intent, null, -1, null, false, mContext.getOpPackageName(),
|
||||
UserHandle.USER_SYSTEM);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
|
||||
@@ -525,6 +525,12 @@ public class MockContext extends Context {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startForegroundService(Intent service) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** STOPSHIP remove when trial API is turned down */
|
||||
@Override
|
||||
public ComponentName startServiceInForeground(Intent service,
|
||||
int id, Notification notification) {
|
||||
@@ -544,6 +550,12 @@ public class MockContext extends Context {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** @hide STOPSHIP removed when trial API is turned down */
|
||||
@Override
|
||||
public ComponentName startServiceInForegroundAsUser(Intent service,
|
||||
int id, Notification notification, UserHandle user) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
@@ -1852,6 +1852,18 @@ public class BridgeContext extends Context {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startForegroundService(Intent service) {
|
||||
// pass
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
|
||||
// pass
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startServiceInForeground(Intent service,
|
||||
int id, Notification notification) {
|
||||
|
||||
Reference in New Issue
Block a user