Merge "API refactor: context.startForegroundService()" into oc-dev

This commit is contained in:
TreeHugger Robot
2017-03-30 20:54:18 +00:00
committed by Android (Google) Code Review
19 changed files with 265 additions and 50 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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