FileDocCategorySizeDatePackage
ServiceRecord.javaAPI DocAndroid 5.1 API25432Thu Mar 12 22:22:42 GMT 2015com.android.server.am

ServiceRecord

public final class ServiceRecord extends android.os.Binder
A running application service.

Fields Summary
static final int
MAX_DELIVERY_COUNT
static final int
MAX_DONE_EXECUTING_COUNT
final ActivityManagerService
ams
final BatteryStatsImpl.Uid.Pkg.Serv
stats
final android.content.ComponentName
name
final String
shortName
final Intent.FilterComparison
intent
final android.content.pm.ServiceInfo
serviceInfo
final android.content.pm.ApplicationInfo
appInfo
final int
userId
final String
packageName
final String
processName
final String
permission
final boolean
exported
final Runnable
restarter
final long
createTime
final android.util.ArrayMap
bindings
final android.util.ArrayMap
connections
ProcessRecord
app
ProcessRecord
isolatedProc
ProcessStats.ServiceState
tracker
ProcessStats.ServiceState
restartTracker
boolean
delayed
boolean
isForeground
int
foregroundId
android.app.Notification
foregroundNoti
long
lastActivity
long
startingBgTimeout
boolean
startRequested
boolean
delayedStop
boolean
stopIfKilled
boolean
callStart
int
executeNesting
boolean
executeFg
long
executingStart
boolean
createdFromFg
int
crashCount
int
totalRestartCount
int
restartCount
long
restartDelay
long
restartTime
long
nextRestartTime
boolean
destroying
long
destroyTime
String
stringName
private int
lastStartId
final ArrayList
deliveredStarts
final ArrayList
pendingStarts
Constructors Summary
ServiceRecord(ActivityManagerService ams, BatteryStatsImpl.Uid.Pkg.Serv servStats, android.content.ComponentName name, Intent.FilterComparison intent, android.content.pm.ServiceInfo sInfo, boolean callerIsFg, Runnable restarter)

        this.ams = ams;
        this.stats = servStats;
        this.name = name;
        shortName = name.flattenToShortString();
        this.intent = intent;
        serviceInfo = sInfo;
        appInfo = sInfo.applicationInfo;
        packageName = sInfo.applicationInfo.packageName;
        processName = sInfo.processName;
        permission = sInfo.permission;
        exported = sInfo.exported;
        this.restarter = restarter;
        createTime = SystemClock.elapsedRealtime();
        lastActivity = SystemClock.uptimeMillis();
        userId = UserHandle.getUserId(appInfo.uid);
        createdFromFg = callerIsFg;
    
Methods Summary
public voidcancelNotification()

        if (foregroundId != 0) {
            // Do asynchronous communication with notification manager to
            // avoid deadlocks.
            final String localPackageName = packageName;
            final int localForegroundId = foregroundId;
            ams.mHandler.post(new Runnable() {
                public void run() {
                    INotificationManager inm = NotificationManager.getService();
                    if (inm == null) {
                        return;
                    }
                    try {
                        inm.cancelNotificationWithTag(localPackageName, null,
                                localForegroundId, userId);
                    } catch (RuntimeException e) {
                        Slog.w(ActivityManagerService.TAG,
                                "Error canceling notification for service", e);
                    } catch (RemoteException e) {
                    }
                }
            });
        }
    
public voidclearDeliveredStartsLocked()

        for (int i=deliveredStarts.size()-1; i>=0; i--) {
            deliveredStarts.get(i).removeUriPermissionsLocked();
        }
        deliveredStarts.clear();
    
voiddump(java.io.PrintWriter pw, java.lang.String prefix)

        pw.print(prefix); pw.print("intent={");
                pw.print(intent.getIntent().toShortString(false, true, false, true));
                pw.println('}");
        pw.print(prefix); pw.print("packageName="); pw.println(packageName);
        pw.print(prefix); pw.print("processName="); pw.println(processName);
        if (permission != null) {
            pw.print(prefix); pw.print("permission="); pw.println(permission);
        }
        long now = SystemClock.uptimeMillis();
        long nowReal = SystemClock.elapsedRealtime();
        if (appInfo != null) {
            pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
            if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
                pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
            }
            pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
        }
        pw.print(prefix); pw.print("app="); pw.println(app);
        if (isolatedProc != null) {
            pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
        }
        if (delayed) {
            pw.print(prefix); pw.print("delayed="); pw.println(delayed);
        }
        if (isForeground || foregroundId != 0) {
            pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
                    pw.print(" foregroundId="); pw.print(foregroundId);
                    pw.print(" foregroundNoti="); pw.println(foregroundNoti);
        }
        pw.print(prefix); pw.print("createTime=");
                TimeUtils.formatDuration(createTime, nowReal, pw);
                pw.print(" startingBgTimeout=");
                TimeUtils.formatDuration(startingBgTimeout, now, pw);
                pw.println();
        pw.print(prefix); pw.print("lastActivity=");
                TimeUtils.formatDuration(lastActivity, now, pw);
                pw.print(" restartTime=");
                TimeUtils.formatDuration(restartTime, now, pw);
                pw.print(" createdFromFg="); pw.println(createdFromFg);
        if (startRequested || delayedStop || lastStartId != 0) {
            pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
                    pw.print(" delayedStop="); pw.print(delayedStop);
                    pw.print(" stopIfKilled="); pw.print(stopIfKilled);
                    pw.print(" callStart="); pw.print(callStart);
                    pw.print(" lastStartId="); pw.println(lastStartId);
        }
        if (executeNesting != 0) {
            pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting);
                    pw.print(" executeFg="); pw.print(executeFg);
                    pw.print(" executingStart=");
                    TimeUtils.formatDuration(executingStart, now, pw);
                    pw.println();
        }
        if (destroying || destroyTime != 0) {
            pw.print(prefix); pw.print("destroying="); pw.print(destroying);
                    pw.print(" destroyTime=");
                    TimeUtils.formatDuration(destroyTime, now, pw);
                    pw.println();
        }
        if (crashCount != 0 || restartCount != 0
                || restartDelay != 0 || nextRestartTime != 0) {
            pw.print(prefix); pw.print("restartCount="); pw.print(restartCount);
                    pw.print(" restartDelay=");
                    TimeUtils.formatDuration(restartDelay, now, pw);
                    pw.print(" nextRestartTime=");
                    TimeUtils.formatDuration(nextRestartTime, now, pw);
                    pw.print(" crashCount="); pw.println(crashCount);
        }
        if (deliveredStarts.size() > 0) {
            pw.print(prefix); pw.println("Delivered Starts:");
            dumpStartList(pw, prefix, deliveredStarts, now);
        }
        if (pendingStarts.size() > 0) {
            pw.print(prefix); pw.println("Pending Starts:");
            dumpStartList(pw, prefix, pendingStarts, 0);
        }
        if (bindings.size() > 0) {
            pw.print(prefix); pw.println("Bindings:");
            for (int i=0; i<bindings.size(); i++) {
                IntentBindRecord b = bindings.valueAt(i);
                pw.print(prefix); pw.print("* IntentBindRecord{");
                        pw.print(Integer.toHexString(System.identityHashCode(b)));
                        if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
                            pw.append(" CREATE");
                        }
                        pw.println("}:");
                b.dumpInService(pw, prefix + "  ");
            }
        }
        if (connections.size() > 0) {
            pw.print(prefix); pw.println("All Connections:");
            for (int conni=0; conni<connections.size(); conni++) {
                ArrayList<ConnectionRecord> c = connections.valueAt(conni);
                for (int i=0; i<c.size(); i++) {
                    pw.print(prefix); pw.print("  "); pw.println(c.get(i));
                }
            }
        }
    
voiddumpStartList(java.io.PrintWriter pw, java.lang.String prefix, java.util.List list, long now)

                            // start() arguments that haven't yet been delivered.

             
        final int N = list.size();
        for (int i=0; i<N; i++) {
            StartItem si = list.get(i);
            pw.print(prefix); pw.print("#"); pw.print(i);
                    pw.print(" id="); pw.print(si.id);
                    if (now != 0) {
                        pw.print(" dur=");
                        TimeUtils.formatDuration(si.deliveredTime, now, pw);
                    }
                    if (si.deliveryCount != 0) {
                        pw.print(" dc="); pw.print(si.deliveryCount);
                    }
                    if (si.doneExecutingCount != 0) {
                        pw.print(" dxc="); pw.print(si.doneExecutingCount);
                    }
                    pw.println("");
            pw.print(prefix); pw.print("  intent=");
                    if (si.intent != null) pw.println(si.intent.toString());
                    else pw.println("null");
            if (si.neededGrants != null) {
                pw.print(prefix); pw.print("  neededGrants=");
                        pw.println(si.neededGrants);
            }
            if (si.uriPermissions != null) {
                si.uriPermissions.dump(pw, prefix);
            }
        }
    
public com.android.server.am.ServiceRecord$StartItemfindDeliveredStart(int id, boolean remove)

        final int N = deliveredStarts.size();
        for (int i=0; i<N; i++) {
            StartItem si = deliveredStarts.get(i);
            if (si.id == id) {
                if (remove) deliveredStarts.remove(i);
                return si;
            }
        }
        
        return null;
    
public voidforceClearTracker()

        if (tracker != null) {
            tracker.clearCurrentOwner(this, true);
            tracker = null;
        }
    
public intgetLastStartId()

        return lastStartId;
    
public ProcessStats.ServiceStategetTracker()

        if (tracker != null) {
            return tracker;
        }
        if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
            tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
                    serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode,
                    serviceInfo.processName, serviceInfo.name);
            tracker.applyNewOwner(this);
        }
        return tracker;
    
public booleanhasAutoCreateConnections()

        // XXX should probably keep a count of the number of auto-create
        // connections directly in the service.
        for (int conni=connections.size()-1; conni>=0; conni--) {
            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
            for (int i=0; i<cr.size(); i++) {
                if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
                    return true;
                }
            }
        }
        return false;
    
public intmakeNextStartId()

        lastStartId++;
        if (lastStartId < 1) {
            lastStartId = 1;
        }
        return lastStartId;
    
public voidmakeRestarting(int memFactor, long now)

        if (restartTracker == null) {
            if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
                restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
                        serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode,
                        serviceInfo.processName, serviceInfo.name);
            }
            if (restartTracker == null) {
                return;
            }
        }
        restartTracker.setRestarting(true, memFactor, now);
    
public voidpostNotification()

        final int appUid = appInfo.uid;
        final int appPid = app.pid;
        if (foregroundId != 0 && foregroundNoti != null) {
            // Do asynchronous communication with notification manager to
            // avoid deadlocks.
            final String localPackageName = packageName;
            final int localForegroundId = foregroundId;
            final Notification localForegroundNoti = foregroundNoti;
            ams.mHandler.post(new Runnable() {
                public void run() {
                    NotificationManagerInternal nm = LocalServices.getService(
                            NotificationManagerInternal.class);
                    if (nm == null) {
                        return;
                    }
                    try {
                        if (localForegroundNoti.icon == 0) {
                            // It is not correct for the caller to supply a notification
                            // icon, but this used to be able to slip through, so for
                            // those dirty apps give it the app's icon.
                            localForegroundNoti.icon = appInfo.icon;

                            // Do not allow apps to present a sneaky invisible content view either.
                            localForegroundNoti.contentView = null;
                            localForegroundNoti.bigContentView = null;
                            CharSequence appName = appInfo.loadLabel(
                                    ams.mContext.getPackageManager());
                            if (appName == null) {
                                appName = appInfo.packageName;
                            }
                            Context ctx = null;
                            try {
                                ctx = ams.mContext.createPackageContext(
                                        appInfo.packageName, 0);
                                Intent runningIntent = new Intent(
                                        Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                runningIntent.setData(Uri.fromParts("package",
                                        appInfo.packageName, null));
                                PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
                                        runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                                localForegroundNoti.color = ams.mContext.getResources().getColor(
                                        com.android.internal
                                                .R.color.system_notification_accent_color);
                                localForegroundNoti.setLatestEventInfo(ctx,
                                        ams.mContext.getString(
                                                com.android.internal.R.string
                                                        .app_running_notification_title,
                                                appName),
                                        ams.mContext.getString(
                                                com.android.internal.R.string
                                                        .app_running_notification_text,
                                                appName),
                                        pi);
                            } catch (PackageManager.NameNotFoundException e) {
                                localForegroundNoti.icon = 0;
                            }
                        }
                        if (localForegroundNoti.icon == 0) {
                            // Notifications whose icon is 0 are defined to not show
                            // a notification, silently ignoring it.  We don't want to
                            // just ignore it, we want to prevent the service from
                            // being foreground.
                            throw new RuntimeException("icon must be non-zero");
                        }
                        int[] outId = new int[1];
                        nm.enqueueNotification(localPackageName, localPackageName,
                                appUid, appPid, null, localForegroundId, localForegroundNoti,
                                outId, userId);
                    } catch (RuntimeException e) {
                        Slog.w(ActivityManagerService.TAG,
                                "Error showing notification for service", e);
                        // If it gave us a garbage notification, it doesn't
                        // get to be foreground.
                        ams.setServiceForeground(name, ServiceRecord.this,
                                0, null, true);
                        ams.crashApplication(appUid, appPid, localPackageName,
                                "Bad notification for startForeground: " + e);
                    }
                }
            });
        }
    
public voidresetRestartCounter()

        restartCount = 0;
        restartDelay = 0;
        restartTime = 0;
    
public AppBindRecordretrieveAppBindingLocked(android.content.Intent intent, ProcessRecord app)

        Intent.FilterComparison filter = new Intent.FilterComparison(intent);
        IntentBindRecord i = bindings.get(filter);
        if (i == null) {
            i = new IntentBindRecord(this, filter);
            bindings.put(filter, i);
        }
        AppBindRecord a = i.apps.get(app);
        if (a != null) {
            return a;
        }
        a = new AppBindRecord(this, i, app);
        i.apps.put(app, a);
        return a;
    
public voidstripForegroundServiceFlagFromNotification()

        if (foregroundId == 0) {
            return;
        }

        final int localForegroundId = foregroundId;
        final int localUserId = userId;
        final String localPackageName = packageName;

        // Do asynchronous communication with notification manager to
        // avoid deadlocks.
        ams.mHandler.post(new Runnable() {
            @Override
            public void run() {
                NotificationManagerInternal nmi = LocalServices.getService(
                        NotificationManagerInternal.class);
                if (nmi == null) {
                    return;
                }
                nmi.removeForegroundServiceFlagFromNotification(localPackageName, localForegroundId,
                        localUserId);
            }
        });
    
public java.lang.StringtoString()

        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("ServiceRecord{")
            .append(Integer.toHexString(System.identityHashCode(this)))
            .append(" u").append(userId)
            .append(' ").append(shortName).append('}");
        return stringName = sb.toString();