ActiveServices.java revision 5ac72a29593ab9a20337a2225df52bdf4754be02
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import java.io.FileDescriptor;
20import java.io.IOException;
21import java.io.PrintWriter;
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Iterator;
27import java.util.List;
28
29import com.android.internal.os.BatteryStatsImpl;
30import com.android.server.am.ActivityManagerService.ItemMatcher;
31import com.android.server.am.ActivityManagerService.NeededUriGrants;
32
33import android.app.ActivityManager;
34import android.app.AppGlobals;
35import android.app.IApplicationThread;
36import android.app.IServiceConnection;
37import android.app.Notification;
38import android.app.PendingIntent;
39import android.app.Service;
40import android.content.ComponentName;
41import android.content.Context;
42import android.content.Intent;
43import android.content.pm.ApplicationInfo;
44import android.content.pm.PackageManager;
45import android.content.pm.ResolveInfo;
46import android.content.pm.ServiceInfo;
47import android.content.pm.UserInfo;
48import android.os.Binder;
49import android.os.IBinder;
50import android.os.Message;
51import android.os.Process;
52import android.os.RemoteException;
53import android.os.SystemClock;
54import android.os.UserHandle;
55import android.util.EventLog;
56import android.util.Log;
57import android.util.Slog;
58import android.util.SparseArray;
59import android.util.TimeUtils;
60
61public class ActiveServices {
62    static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
63    static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
64    static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
65    static final String TAG = ActivityManagerService.TAG;
66    static final String TAG_MU = ActivityManagerService.TAG_MU;
67
68    // How long we wait for a service to finish executing.
69    static final int SERVICE_TIMEOUT = 20*1000;
70
71    // How long a service needs to be running until restarting its process
72    // is no longer considered to be a relaunch of the service.
73    static final int SERVICE_RESTART_DURATION = 5*1000;
74
75    // How long a service needs to be running until it will start back at
76    // SERVICE_RESTART_DURATION after being killed.
77    static final int SERVICE_RESET_RUN_DURATION = 60*1000;
78
79    // Multiplying factor to increase restart duration time by, for each time
80    // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
81    static final int SERVICE_RESTART_DURATION_FACTOR = 4;
82
83    // The minimum amount of time between restarting services that we allow.
84    // That is, when multiple services are restarting, we won't allow each
85    // to restart less than this amount of time from the last one.
86    static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
87
88    // Maximum amount of time for there to be no activity on a service before
89    // we consider it non-essential and allow its process to go on the
90    // LRU background list.
91    static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
92
93    final ActivityManagerService mAm;
94
95    final ServiceMap mServiceMap = new ServiceMap();
96
97    /**
98     * All currently bound service connections.  Keys are the IBinder of
99     * the client's IServiceConnection.
100     */
101    final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
102            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
103
104    /**
105     * List of services that we have been asked to start,
106     * but haven't yet been able to.  It is used to hold start requests
107     * while waiting for their corresponding application thread to get
108     * going.
109     */
110    final ArrayList<ServiceRecord> mPendingServices
111            = new ArrayList<ServiceRecord>();
112
113    /**
114     * List of services that are scheduled to restart following a crash.
115     */
116    final ArrayList<ServiceRecord> mRestartingServices
117            = new ArrayList<ServiceRecord>();
118
119    /**
120     * List of services that are in the process of being stopped.
121     */
122    final ArrayList<ServiceRecord> mStoppingServices
123            = new ArrayList<ServiceRecord>();
124
125    static class ServiceMap {
126
127        private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
128                = new SparseArray<HashMap<ComponentName, ServiceRecord>>();
129        private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
130                mServicesByIntentPerUser = new SparseArray<
131                    HashMap<Intent.FilterComparison, ServiceRecord>>();
132
133        ServiceRecord getServiceByName(ComponentName name, int callingUser) {
134            // TODO: Deal with global services
135            if (DEBUG_MU)
136                Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
137            return getServices(callingUser).get(name);
138        }
139
140        ServiceRecord getServiceByName(ComponentName name) {
141            return getServiceByName(name, -1);
142        }
143
144        ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
145            // TODO: Deal with global services
146            if (DEBUG_MU)
147                Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
148            return getServicesByIntent(callingUser).get(filter);
149        }
150
151        ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
152            return getServiceByIntent(filter, -1);
153        }
154
155        void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
156            // TODO: Deal with global services
157            getServices(callingUser).put(name, value);
158        }
159
160        void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
161                ServiceRecord value) {
162            // TODO: Deal with global services
163            getServicesByIntent(callingUser).put(filter, value);
164        }
165
166        void removeServiceByName(ComponentName name, int callingUser) {
167            // TODO: Deal with global services
168            ServiceRecord removed = getServices(callingUser).remove(name);
169            if (DEBUG_MU)
170                Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
171                        + " removed=" + removed);
172        }
173
174        void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
175            // TODO: Deal with global services
176            ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
177            if (DEBUG_MU)
178                Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
179                        + " removed=" + removed);
180        }
181
182        Collection<ServiceRecord> getAllServices(int callingUser) {
183            // TODO: Deal with global services
184            return getServices(callingUser).values();
185        }
186
187        private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
188            HashMap map = mServicesByNamePerUser.get(callingUser);
189            if (map == null) {
190                map = new HashMap<ComponentName, ServiceRecord>();
191                mServicesByNamePerUser.put(callingUser, map);
192            }
193            return map;
194        }
195
196        private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
197                int callingUser) {
198            HashMap map = mServicesByIntentPerUser.get(callingUser);
199            if (map == null) {
200                map = new HashMap<Intent.FilterComparison, ServiceRecord>();
201                mServicesByIntentPerUser.put(callingUser, map);
202            }
203            return map;
204        }
205    }
206
207    public ActiveServices(ActivityManagerService service) {
208        mAm = service;
209    }
210
211    ComponentName startServiceLocked(IApplicationThread caller,
212            Intent service, String resolvedType,
213            int callingPid, int callingUid, int userId) {
214        if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
215                + " type=" + resolvedType + " args=" + service.getExtras());
216
217        if (caller != null) {
218            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
219            if (callerApp == null) {
220                throw new SecurityException(
221                        "Unable to find app for caller " + caller
222                        + " (pid=" + Binder.getCallingPid()
223                        + ") when starting service " + service);
224            }
225        }
226
227        ServiceLookupResult res =
228            retrieveServiceLocked(service, resolvedType,
229                    callingPid, callingUid, userId, true);
230        if (res == null) {
231            return null;
232        }
233        if (res.record == null) {
234            return new ComponentName("!", res.permission != null
235                    ? res.permission : "private to package");
236        }
237        ServiceRecord r = res.record;
238        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
239                callingUid, r.packageName, service, service.getFlags(), null);
240        if (unscheduleServiceRestartLocked(r)) {
241            if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
242        }
243        r.startRequested = true;
244        r.callStart = false;
245        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
246                service, neededGrants));
247        r.lastActivity = SystemClock.uptimeMillis();
248        synchronized (r.stats.getBatteryStats()) {
249            r.stats.startRunningLocked();
250        }
251        if (!bringUpServiceLocked(r, service.getFlags(), false)) {
252            return new ComponentName("!", "Service process is bad");
253        }
254        return r.name;
255    }
256
257    private void stopServiceLocked(ServiceRecord service) {
258        synchronized (service.stats.getBatteryStats()) {
259            service.stats.stopRunningLocked();
260        }
261        service.startRequested = false;
262        service.callStart = false;
263        bringDownServiceLocked(service, false);
264    }
265
266    int stopServiceLocked(IApplicationThread caller, Intent service,
267            String resolvedType, int userId) {
268        if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
269                + " type=" + resolvedType);
270
271        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
272        if (caller != null && callerApp == null) {
273            throw new SecurityException(
274                    "Unable to find app for caller " + caller
275                    + " (pid=" + Binder.getCallingPid()
276                    + ") when stopping service " + service);
277        }
278
279        // If this service is active, make sure it is stopped.
280        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
281                Binder.getCallingPid(), Binder.getCallingUid(), userId, false);
282        if (r != null) {
283            if (r.record != null) {
284                final long origId = Binder.clearCallingIdentity();
285                try {
286                    stopServiceLocked(r.record);
287                } finally {
288                    Binder.restoreCallingIdentity(origId);
289                }
290                return 1;
291            }
292            return -1;
293        }
294
295        return 0;
296    }
297
298    IBinder peekServiceLocked(Intent service, String resolvedType) {
299        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
300                Binder.getCallingPid(), Binder.getCallingUid(),
301                UserHandle.getCallingUserId(), false);
302
303        IBinder ret = null;
304        if (r != null) {
305            // r.record is null if findServiceLocked() failed the caller permission check
306            if (r.record == null) {
307                throw new SecurityException(
308                        "Permission Denial: Accessing service " + r.record.name
309                        + " from pid=" + Binder.getCallingPid()
310                        + ", uid=" + Binder.getCallingUid()
311                        + " requires " + r.permission);
312            }
313            IntentBindRecord ib = r.record.bindings.get(r.record.intent);
314            if (ib != null) {
315                ret = ib.binder;
316            }
317        }
318
319        return ret;
320    }
321
322    boolean stopServiceTokenLocked(ComponentName className, IBinder token,
323            int startId) {
324        if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
325                + " " + token + " startId=" + startId);
326        ServiceRecord r = findServiceLocked(className, token);
327        if (r != null) {
328            if (startId >= 0) {
329                // Asked to only stop if done with all work.  Note that
330                // to avoid leaks, we will take this as dropping all
331                // start items up to and including this one.
332                ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
333                if (si != null) {
334                    while (r.deliveredStarts.size() > 0) {
335                        ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
336                        cur.removeUriPermissionsLocked();
337                        if (cur == si) {
338                            break;
339                        }
340                    }
341                }
342
343                if (r.getLastStartId() != startId) {
344                    return false;
345                }
346
347                if (r.deliveredStarts.size() > 0) {
348                    Slog.w(TAG, "stopServiceToken startId " + startId
349                            + " is last, but have " + r.deliveredStarts.size()
350                            + " remaining args");
351                }
352            }
353
354            synchronized (r.stats.getBatteryStats()) {
355                r.stats.stopRunningLocked();
356                r.startRequested = false;
357                r.callStart = false;
358            }
359            final long origId = Binder.clearCallingIdentity();
360            bringDownServiceLocked(r, false);
361            Binder.restoreCallingIdentity(origId);
362            return true;
363        }
364        return false;
365    }
366
367    public void setServiceForegroundLocked(ComponentName className, IBinder token,
368            int id, Notification notification, boolean removeNotification) {
369        final long origId = Binder.clearCallingIdentity();
370        try {
371            ServiceRecord r = findServiceLocked(className, token);
372            if (r != null) {
373                if (id != 0) {
374                    if (notification == null) {
375                        throw new IllegalArgumentException("null notification");
376                    }
377                    if (r.foregroundId != id) {
378                        r.cancelNotification();
379                        r.foregroundId = id;
380                    }
381                    notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
382                    r.foregroundNoti = notification;
383                    r.isForeground = true;
384                    r.postNotification();
385                    if (r.app != null) {
386                        updateServiceForegroundLocked(r.app, true);
387                    }
388                } else {
389                    if (r.isForeground) {
390                        r.isForeground = false;
391                        if (r.app != null) {
392                            mAm.updateLruProcessLocked(r.app, false, true);
393                            updateServiceForegroundLocked(r.app, true);
394                        }
395                    }
396                    if (removeNotification) {
397                        r.cancelNotification();
398                        r.foregroundId = 0;
399                        r.foregroundNoti = null;
400                    }
401                }
402            }
403        } finally {
404            Binder.restoreCallingIdentity(origId);
405        }
406    }
407
408    private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
409        boolean anyForeground = false;
410        for (ServiceRecord sr : proc.services) {
411            if (sr.isForeground) {
412                anyForeground = true;
413                break;
414            }
415        }
416        if (anyForeground != proc.foregroundServices) {
417            proc.foregroundServices = anyForeground;
418            if (oomAdj) {
419                mAm.updateOomAdjLocked();
420            }
421        }
422    }
423
424    int bindServiceLocked(IApplicationThread caller, IBinder token,
425            Intent service, String resolvedType,
426            IServiceConnection connection, int flags, int userId) {
427        if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
428                + " type=" + resolvedType + " conn=" + connection.asBinder()
429                + " flags=0x" + Integer.toHexString(flags));
430        if (DEBUG_MU)
431            Slog.i(TAG_MU, "bindService uid=" + Binder.getCallingUid() + " origUid="
432                    + Binder.getOrigCallingUid());
433        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
434        if (callerApp == null) {
435            throw new SecurityException(
436                    "Unable to find app for caller " + caller
437                    + " (pid=" + Binder.getCallingPid()
438                    + ") when binding service " + service);
439        }
440
441        ActivityRecord activity = null;
442        if (token != null) {
443            activity = mAm.mMainStack.isInStackLocked(token);
444            if (activity == null) {
445                Slog.w(TAG, "Binding with unknown activity: " + token);
446                return 0;
447            }
448        }
449
450        int clientLabel = 0;
451        PendingIntent clientIntent = null;
452
453        if (callerApp.info.uid == Process.SYSTEM_UID) {
454            // Hacky kind of thing -- allow system stuff to tell us
455            // what they are, so we can report this elsewhere for
456            // others to know why certain services are running.
457            try {
458                clientIntent = (PendingIntent)service.getParcelableExtra(
459                        Intent.EXTRA_CLIENT_INTENT);
460            } catch (RuntimeException e) {
461            }
462            if (clientIntent != null) {
463                clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
464                if (clientLabel != 0) {
465                    // There are no useful extras in the intent, trash them.
466                    // System code calling with this stuff just needs to know
467                    // this will happen.
468                    service = service.cloneFilter();
469                }
470            }
471        }
472
473        ServiceLookupResult res =
474            retrieveServiceLocked(service, resolvedType,
475                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
476        if (res == null) {
477            return 0;
478        }
479        if (res.record == null) {
480            return -1;
481        }
482        if (mAm.isSingleton(res.record.processName, res.record.appInfo,
483                res.record.serviceInfo.name, res.record.serviceInfo.flags)) {
484            userId = 0;
485            res = retrieveServiceLocked(service, resolvedType, Binder.getCallingPid(),
486                    Binder.getCallingUid(), 0, true);
487        }
488        ServiceRecord s = res.record;
489
490        final long origId = Binder.clearCallingIdentity();
491
492        try {
493            if (unscheduleServiceRestartLocked(s)) {
494                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
495                        + s);
496            }
497
498            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
499            ConnectionRecord c = new ConnectionRecord(b, activity,
500                    connection, flags, clientLabel, clientIntent);
501
502            IBinder binder = connection.asBinder();
503            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
504            if (clist == null) {
505                clist = new ArrayList<ConnectionRecord>();
506                s.connections.put(binder, clist);
507            }
508            clist.add(c);
509            b.connections.add(c);
510            if (activity != null) {
511                if (activity.connections == null) {
512                    activity.connections = new HashSet<ConnectionRecord>();
513                }
514                activity.connections.add(c);
515            }
516            b.client.connections.add(c);
517            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
518                b.client.hasAboveClient = true;
519            }
520            clist = mServiceConnections.get(binder);
521            if (clist == null) {
522                clist = new ArrayList<ConnectionRecord>();
523                mServiceConnections.put(binder, clist);
524            }
525            clist.add(c);
526
527            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
528                s.lastActivity = SystemClock.uptimeMillis();
529                if (!bringUpServiceLocked(s, service.getFlags(), false)) {
530                    return 0;
531                }
532            }
533
534            if (s.app != null) {
535                // This could have made the service more important.
536                mAm.updateOomAdjLocked(s.app);
537            }
538
539            if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
540                    + ": received=" + b.intent.received
541                    + " apps=" + b.intent.apps.size()
542                    + " doRebind=" + b.intent.doRebind);
543
544            if (s.app != null && b.intent.received) {
545                // Service is already running, so we can immediately
546                // publish the connection.
547                try {
548                    c.conn.connected(s.name, b.intent.binder);
549                } catch (Exception e) {
550                    Slog.w(TAG, "Failure sending service " + s.shortName
551                            + " to connection " + c.conn.asBinder()
552                            + " (in " + c.binding.client.processName + ")", e);
553                }
554
555                // If this is the first app connected back to this binding,
556                // and the service had previously asked to be told when
557                // rebound, then do so.
558                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
559                    requestServiceBindingLocked(s, b.intent, true);
560                }
561            } else if (!b.intent.requested) {
562                requestServiceBindingLocked(s, b.intent, false);
563            }
564        } finally {
565            Binder.restoreCallingIdentity(origId);
566        }
567
568        return 1;
569    }
570
571    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
572        final long origId = Binder.clearCallingIdentity();
573        try {
574            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
575                    + " " + intent + ": " + service);
576            if (r != null) {
577                Intent.FilterComparison filter
578                        = new Intent.FilterComparison(intent);
579                IntentBindRecord b = r.bindings.get(filter);
580                if (b != null && !b.received) {
581                    b.binder = service;
582                    b.requested = true;
583                    b.received = true;
584                    if (r.connections.size() > 0) {
585                        Iterator<ArrayList<ConnectionRecord>> it
586                                = r.connections.values().iterator();
587                        while (it.hasNext()) {
588                            ArrayList<ConnectionRecord> clist = it.next();
589                            for (int i=0; i<clist.size(); i++) {
590                                ConnectionRecord c = clist.get(i);
591                                if (!filter.equals(c.binding.intent.intent)) {
592                                    if (DEBUG_SERVICE) Slog.v(
593                                            TAG, "Not publishing to: " + c);
594                                    if (DEBUG_SERVICE) Slog.v(
595                                            TAG, "Bound intent: " + c.binding.intent.intent);
596                                    if (DEBUG_SERVICE) Slog.v(
597                                            TAG, "Published intent: " + intent);
598                                    continue;
599                                }
600                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
601                                try {
602                                    c.conn.connected(r.name, service);
603                                } catch (Exception e) {
604                                    Slog.w(TAG, "Failure sending service " + r.name +
605                                          " to connection " + c.conn.asBinder() +
606                                          " (in " + c.binding.client.processName + ")", e);
607                                }
608                            }
609                        }
610                    }
611                }
612
613                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
614            }
615        } finally {
616            Binder.restoreCallingIdentity(origId);
617        }
618    }
619
620    boolean unbindServiceLocked(IServiceConnection connection) {
621        IBinder binder = connection.asBinder();
622        if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
623        ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
624        if (clist == null) {
625            Slog.w(TAG, "Unbind failed: could not find connection for "
626                  + connection.asBinder());
627            return false;
628        }
629
630        final long origId = Binder.clearCallingIdentity();
631        try {
632            while (clist.size() > 0) {
633                ConnectionRecord r = clist.get(0);
634                removeConnectionLocked(r, null, null);
635
636                if (r.binding.service.app != null) {
637                    // This could have made the service less important.
638                    mAm.updateOomAdjLocked(r.binding.service.app);
639                }
640            }
641        } finally {
642            Binder.restoreCallingIdentity(origId);
643        }
644
645        return true;
646    }
647
648    void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) {
649        final long origId = Binder.clearCallingIdentity();
650        try {
651            if (r != null) {
652                Intent.FilterComparison filter
653                        = new Intent.FilterComparison(intent);
654                IntentBindRecord b = r.bindings.get(filter);
655                if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
656                        + " at " + b + ": apps="
657                        + (b != null ? b.apps.size() : 0));
658
659                boolean inStopping = mStoppingServices.contains(r);
660                if (b != null) {
661                    if (b.apps.size() > 0 && !inStopping) {
662                        // Applications have already bound since the last
663                        // unbind, so just rebind right here.
664                        requestServiceBindingLocked(r, b, true);
665                    } else {
666                        // Note to tell the service the next time there is
667                        // a new client.
668                        b.doRebind = true;
669                    }
670                }
671
672                serviceDoneExecutingLocked(r, inStopping);
673            }
674        } finally {
675            Binder.restoreCallingIdentity(origId);
676        }
677    }
678
679    private final ServiceRecord findServiceLocked(ComponentName name,
680            IBinder token) {
681        ServiceRecord r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
682        return r == token ? r : null;
683    }
684
685    private final class ServiceLookupResult {
686        final ServiceRecord record;
687        final String permission;
688
689        ServiceLookupResult(ServiceRecord _record, String _permission) {
690            record = _record;
691            permission = _permission;
692        }
693    }
694
695    private class ServiceRestarter implements Runnable {
696        private ServiceRecord mService;
697
698        void setService(ServiceRecord service) {
699            mService = service;
700        }
701
702        public void run() {
703            synchronized(mAm) {
704                performServiceRestartLocked(mService);
705            }
706        }
707    }
708
709    private ServiceLookupResult retrieveServiceLocked(Intent service,
710            String resolvedType, int callingPid, int callingUid, int userId,
711            boolean createIfNeeded) {
712        ServiceRecord r = null;
713        if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
714                + " type=" + resolvedType + " callingUid=" + callingUid);
715
716        userId = mAm.handleIncomingUserLocked(callingPid, callingUid, userId,
717                false, true, "service", null);
718
719        if (service.getComponent() != null) {
720            r = mServiceMap.getServiceByName(service.getComponent(), userId);
721        }
722        if (r == null) {
723            Intent.FilterComparison filter = new Intent.FilterComparison(service);
724            r = mServiceMap.getServiceByIntent(filter, userId);
725        }
726        if (r == null) {
727            try {
728                ResolveInfo rInfo =
729                    AppGlobals.getPackageManager().resolveService(
730                                service, resolvedType,
731                                ActivityManagerService.STOCK_PM_FLAGS, userId);
732                ServiceInfo sInfo =
733                    rInfo != null ? rInfo.serviceInfo : null;
734                if (sInfo == null) {
735                    Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
736                          ": not found");
737                    return null;
738                }
739                ComponentName name = new ComponentName(
740                        sInfo.applicationInfo.packageName, sInfo.name);
741                if (userId > 0) {
742                    if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
743                            sInfo.name, sInfo.flags)) {
744                        userId = 0;
745                    }
746                    sInfo = new ServiceInfo(sInfo);
747                    sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
748                }
749                r = mServiceMap.getServiceByName(name, userId);
750                if (r == null && createIfNeeded) {
751                    Intent.FilterComparison filter = new Intent.FilterComparison(
752                            service.cloneFilter());
753                    ServiceRestarter res = new ServiceRestarter();
754                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
755                    BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
756                    synchronized (stats) {
757                        ss = stats.getServiceStatsLocked(
758                                sInfo.applicationInfo.uid, sInfo.packageName,
759                                sInfo.name);
760                    }
761                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);
762                    res.setService(r);
763                    mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
764                    mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
765
766                    // Make sure this component isn't in the pending list.
767                    int N = mPendingServices.size();
768                    for (int i=0; i<N; i++) {
769                        ServiceRecord pr = mPendingServices.get(i);
770                        if (pr.name.equals(name)) {
771                            mPendingServices.remove(i);
772                            i--;
773                            N--;
774                        }
775                    }
776                }
777            } catch (RemoteException ex) {
778                // pm is in same process, this will never happen.
779            }
780        }
781        if (r != null) {
782            if (mAm.checkComponentPermission(r.permission,
783                    callingPid, callingUid, r.appInfo.uid, r.exported)
784                    != PackageManager.PERMISSION_GRANTED) {
785                if (!r.exported) {
786                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
787                            + " from pid=" + callingPid
788                            + ", uid=" + callingUid
789                            + " that is not exported from uid " + r.appInfo.uid);
790                    return new ServiceLookupResult(null, "not exported from uid "
791                            + r.appInfo.uid);
792                }
793                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
794                        + " from pid=" + callingPid
795                        + ", uid=" + callingUid
796                        + " requires " + r.permission);
797                return new ServiceLookupResult(null, r.permission);
798            }
799            return new ServiceLookupResult(r, null);
800        }
801        return null;
802    }
803
804    private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
805        if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
806                + why + " of " + r + " in app " + r.app);
807        else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
808                + why + " of " + r.shortName);
809        long now = SystemClock.uptimeMillis();
810        if (r.executeNesting == 0 && r.app != null) {
811            if (r.app.executingServices.size() == 0) {
812                Message msg = mAm.mHandler.obtainMessage(
813                        ActivityManagerService.SERVICE_TIMEOUT_MSG);
814                msg.obj = r.app;
815                mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
816            }
817            r.app.executingServices.add(r);
818        }
819        r.executeNesting++;
820        r.executingStart = now;
821    }
822
823    private final boolean requestServiceBindingLocked(ServiceRecord r,
824            IntentBindRecord i, boolean rebind) {
825        if (r.app == null || r.app.thread == null) {
826            // If service is not currently running, can't yet bind.
827            return false;
828        }
829        if ((!i.requested || rebind) && i.apps.size() > 0) {
830            try {
831                bumpServiceExecutingLocked(r, "bind");
832                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
833                if (!rebind) {
834                    i.requested = true;
835                }
836                i.hasBound = true;
837                i.doRebind = false;
838            } catch (RemoteException e) {
839                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
840                return false;
841            }
842        }
843        return true;
844    }
845
846    private final boolean scheduleServiceRestartLocked(ServiceRecord r,
847            boolean allowCancel) {
848        boolean canceled = false;
849
850        final long now = SystemClock.uptimeMillis();
851
852        if ((r.serviceInfo.applicationInfo.flags
853                &ApplicationInfo.FLAG_PERSISTENT) == 0) {
854            long minDuration = SERVICE_RESTART_DURATION;
855            long resetTime = SERVICE_RESET_RUN_DURATION;
856
857            // Any delivered but not yet finished starts should be put back
858            // on the pending list.
859            final int N = r.deliveredStarts.size();
860            if (N > 0) {
861                for (int i=N-1; i>=0; i--) {
862                    ServiceRecord.StartItem si = r.deliveredStarts.get(i);
863                    si.removeUriPermissionsLocked();
864                    if (si.intent == null) {
865                        // We'll generate this again if needed.
866                    } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
867                            && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
868                        r.pendingStarts.add(0, si);
869                        long dur = SystemClock.uptimeMillis() - si.deliveredTime;
870                        dur *= 2;
871                        if (minDuration < dur) minDuration = dur;
872                        if (resetTime < dur) resetTime = dur;
873                    } else {
874                        Slog.w(TAG, "Canceling start item " + si.intent + " in service "
875                                + r.name);
876                        canceled = true;
877                    }
878                }
879                r.deliveredStarts.clear();
880            }
881
882            r.totalRestartCount++;
883            if (r.restartDelay == 0) {
884                r.restartCount++;
885                r.restartDelay = minDuration;
886            } else {
887                // If it has been a "reasonably long time" since the service
888                // was started, then reset our restart duration back to
889                // the beginning, so we don't infinitely increase the duration
890                // on a service that just occasionally gets killed (which is
891                // a normal case, due to process being killed to reclaim memory).
892                if (now > (r.restartTime+resetTime)) {
893                    r.restartCount = 1;
894                    r.restartDelay = minDuration;
895                } else {
896                    if ((r.serviceInfo.applicationInfo.flags
897                            &ApplicationInfo.FLAG_PERSISTENT) != 0) {
898                        // Services in peristent processes will restart much more
899                        // quickly, since they are pretty important.  (Think SystemUI).
900                        r.restartDelay += minDuration/2;
901                    } else {
902                        r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
903                        if (r.restartDelay < minDuration) {
904                            r.restartDelay = minDuration;
905                        }
906                    }
907                }
908            }
909
910            r.nextRestartTime = now + r.restartDelay;
911
912            // Make sure that we don't end up restarting a bunch of services
913            // all at the same time.
914            boolean repeat;
915            do {
916                repeat = false;
917                for (int i=mRestartingServices.size()-1; i>=0; i--) {
918                    ServiceRecord r2 = mRestartingServices.get(i);
919                    if (r2 != r && r.nextRestartTime
920                            >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
921                            && r.nextRestartTime
922                            < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
923                        r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
924                        r.restartDelay = r.nextRestartTime - now;
925                        repeat = true;
926                        break;
927                    }
928                }
929            } while (repeat);
930
931        } else {
932            // Persistent processes are immediately restrted, so there is no
933            // reason to hold of on restarting their services.
934            r.totalRestartCount++;
935            r.restartCount = 0;
936            r.restartDelay = 0;
937            r.nextRestartTime = now;
938        }
939
940        if (!mRestartingServices.contains(r)) {
941            mRestartingServices.add(r);
942        }
943
944        r.cancelNotification();
945
946        mAm.mHandler.removeCallbacks(r.restarter);
947        mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
948        r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
949        Slog.w(TAG, "Scheduling restart of crashed service "
950                + r.shortName + " in " + r.restartDelay + "ms");
951        EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
952                r.shortName, r.restartDelay);
953
954        return canceled;
955    }
956
957    final void performServiceRestartLocked(ServiceRecord r) {
958        if (!mRestartingServices.contains(r)) {
959            return;
960        }
961        bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
962    }
963
964    private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
965        if (r.restartDelay == 0) {
966            return false;
967        }
968        r.resetRestartCounter();
969        mRestartingServices.remove(r);
970        mAm.mHandler.removeCallbacks(r.restarter);
971        return true;
972    }
973
974    private final boolean bringUpServiceLocked(ServiceRecord r,
975            int intentFlags, boolean whileRestarting) {
976        //Slog.i(TAG, "Bring up service:");
977        //r.dump("  ");
978
979        if (r.app != null && r.app.thread != null) {
980            sendServiceArgsLocked(r, false);
981            return true;
982        }
983
984        if (!whileRestarting && r.restartDelay > 0) {
985            // If waiting for a restart, then do nothing.
986            return true;
987        }
988
989        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
990
991        // We are now bringing the service up, so no longer in the
992        // restarting state.
993        mRestartingServices.remove(r);
994
995        // Make sure that the user who owns this service is started.  If not,
996        // we don't want to allow it to run.
997        if (mAm.mStartedUsers.get(r.userId) == null) {
998            Slog.w(TAG, "Unable to launch app "
999                    + r.appInfo.packageName + "/"
1000                    + r.appInfo.uid + " for service "
1001                    + r.intent.getIntent() + ": user " + r.userId + " is stopped");
1002            bringDownServiceLocked(r, true);
1003            return false;
1004        }
1005
1006        // Service is now being launched, its package can't be stopped.
1007        try {
1008            AppGlobals.getPackageManager().setPackageStoppedState(
1009                    r.packageName, false, r.userId);
1010        } catch (RemoteException e) {
1011        } catch (IllegalArgumentException e) {
1012            Slog.w(TAG, "Failed trying to unstop package "
1013                    + r.packageName + ": " + e);
1014        }
1015
1016        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
1017        final String procName = r.processName;
1018        ProcessRecord app;
1019
1020        if (!isolated) {
1021            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
1022            if (DEBUG_MU)
1023                Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
1024            if (app != null && app.thread != null) {
1025                try {
1026                    app.addPackage(r.appInfo.packageName);
1027                    realStartServiceLocked(r, app);
1028                    return true;
1029                } catch (RemoteException e) {
1030                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
1031                }
1032
1033                // If a dead object exception was thrown -- fall through to
1034                // restart the application.
1035            }
1036        } else {
1037            // If this service runs in an isolated process, then each time
1038            // we call startProcessLocked() we will get a new isolated
1039            // process, starting another process if we are currently waiting
1040            // for a previous process to come up.  To deal with this, we store
1041            // in the service any current isolated process it is running in or
1042            // waiting to have come up.
1043            app = r.isolatedProc;
1044        }
1045
1046        // Not running -- get it started, and enqueue this service record
1047        // to be executed when the app comes up.
1048        if (app == null) {
1049            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
1050                    "service", r.name, false, isolated)) == null) {
1051                Slog.w(TAG, "Unable to launch app "
1052                        + r.appInfo.packageName + "/"
1053                        + r.appInfo.uid + " for service "
1054                        + r.intent.getIntent() + ": process is bad");
1055                bringDownServiceLocked(r, true);
1056                return false;
1057            }
1058            if (isolated) {
1059                r.isolatedProc = app;
1060            }
1061        }
1062
1063        if (!mPendingServices.contains(r)) {
1064            mPendingServices.add(r);
1065        }
1066
1067        return true;
1068    }
1069
1070    private final void requestServiceBindingsLocked(ServiceRecord r) {
1071        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
1072        while (bindings.hasNext()) {
1073            IntentBindRecord i = bindings.next();
1074            if (!requestServiceBindingLocked(r, i, false)) {
1075                break;
1076            }
1077        }
1078    }
1079
1080    private final void realStartServiceLocked(ServiceRecord r,
1081            ProcessRecord app) throws RemoteException {
1082        if (app.thread == null) {
1083            throw new RemoteException();
1084        }
1085        if (DEBUG_MU)
1086            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
1087                    + ", ProcessRecord.uid = " + app.uid);
1088        r.app = app;
1089        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
1090
1091        app.services.add(r);
1092        bumpServiceExecutingLocked(r, "create");
1093        mAm.updateLruProcessLocked(app, true, true);
1094
1095        boolean created = false;
1096        try {
1097            mAm.mStringBuilder.setLength(0);
1098            r.intent.getIntent().toShortString(mAm.mStringBuilder, true, false, true, false);
1099            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
1100                    System.identityHashCode(r), r.shortName,
1101                    mAm.mStringBuilder.toString(), r.app.pid);
1102            synchronized (r.stats.getBatteryStats()) {
1103                r.stats.startLaunchedLocked();
1104            }
1105            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
1106            app.thread.scheduleCreateService(r, r.serviceInfo,
1107                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
1108            r.postNotification();
1109            created = true;
1110        } finally {
1111            if (!created) {
1112                app.services.remove(r);
1113                scheduleServiceRestartLocked(r, false);
1114            }
1115        }
1116
1117        requestServiceBindingsLocked(r);
1118
1119        // If the service is in the started state, and there are no
1120        // pending arguments, then fake up one so its onStartCommand() will
1121        // be called.
1122        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
1123            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
1124                    null, null));
1125        }
1126
1127        sendServiceArgsLocked(r, true);
1128    }
1129
1130    private final void sendServiceArgsLocked(ServiceRecord r,
1131            boolean oomAdjusted) {
1132        final int N = r.pendingStarts.size();
1133        if (N == 0) {
1134            return;
1135        }
1136
1137        while (r.pendingStarts.size() > 0) {
1138            try {
1139                ServiceRecord.StartItem si = r.pendingStarts.remove(0);
1140                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
1141                        + r + " " + r.intent + " args=" + si.intent);
1142                if (si.intent == null && N > 1) {
1143                    // If somehow we got a dummy null intent in the middle,
1144                    // then skip it.  DO NOT skip a null intent when it is
1145                    // the only one in the list -- this is to support the
1146                    // onStartCommand(null) case.
1147                    continue;
1148                }
1149                si.deliveredTime = SystemClock.uptimeMillis();
1150                r.deliveredStarts.add(si);
1151                si.deliveryCount++;
1152                if (si.neededGrants != null) {
1153                    mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
1154                            si.getUriPermissionsLocked());
1155                }
1156                bumpServiceExecutingLocked(r, "start");
1157                if (!oomAdjusted) {
1158                    oomAdjusted = true;
1159                    mAm.updateOomAdjLocked(r.app);
1160                }
1161                int flags = 0;
1162                if (si.deliveryCount > 1) {
1163                    flags |= Service.START_FLAG_RETRY;
1164                }
1165                if (si.doneExecutingCount > 0) {
1166                    flags |= Service.START_FLAG_REDELIVERY;
1167                }
1168                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
1169            } catch (RemoteException e) {
1170                // Remote process gone...  we'll let the normal cleanup take
1171                // care of this.
1172                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
1173                break;
1174            } catch (Exception e) {
1175                Slog.w(TAG, "Unexpected exception", e);
1176                break;
1177            }
1178        }
1179    }
1180
1181    private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
1182        //Slog.i(TAG, "Bring down service:");
1183        //r.dump("  ");
1184
1185        // Does it still need to run?
1186        if (!force && r.startRequested) {
1187            return;
1188        }
1189        if (r.connections.size() > 0) {
1190            if (!force) {
1191                // XXX should probably keep a count of the number of auto-create
1192                // connections directly in the service.
1193                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
1194                while (it.hasNext()) {
1195                    ArrayList<ConnectionRecord> cr = it.next();
1196                    for (int i=0; i<cr.size(); i++) {
1197                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
1198                            return;
1199                        }
1200                    }
1201                }
1202            }
1203
1204            // Report to all of the connections that the service is no longer
1205            // available.
1206            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
1207            while (it.hasNext()) {
1208                ArrayList<ConnectionRecord> c = it.next();
1209                for (int i=0; i<c.size(); i++) {
1210                    ConnectionRecord cr = c.get(i);
1211                    // There is still a connection to the service that is
1212                    // being brought down.  Mark it as dead.
1213                    cr.serviceDead = true;
1214                    try {
1215                        cr.conn.connected(r.name, null);
1216                    } catch (Exception e) {
1217                        Slog.w(TAG, "Failure disconnecting service " + r.name +
1218                              " to connection " + c.get(i).conn.asBinder() +
1219                              " (in " + c.get(i).binding.client.processName + ")", e);
1220                    }
1221                }
1222            }
1223        }
1224
1225        // Tell the service that it has been unbound.
1226        if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
1227            Iterator<IntentBindRecord> it = r.bindings.values().iterator();
1228            while (it.hasNext()) {
1229                IntentBindRecord ibr = it.next();
1230                if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
1231                        + ": hasBound=" + ibr.hasBound);
1232                if (r.app != null && r.app.thread != null && ibr.hasBound) {
1233                    try {
1234                        bumpServiceExecutingLocked(r, "bring down unbind");
1235                        mAm.updateOomAdjLocked(r.app);
1236                        ibr.hasBound = false;
1237                        r.app.thread.scheduleUnbindService(r,
1238                                ibr.intent.getIntent());
1239                    } catch (Exception e) {
1240                        Slog.w(TAG, "Exception when unbinding service "
1241                                + r.shortName, e);
1242                        serviceDoneExecutingLocked(r, true);
1243                    }
1244                }
1245            }
1246        }
1247
1248        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
1249        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
1250                System.identityHashCode(r), r.shortName,
1251                (r.app != null) ? r.app.pid : -1);
1252
1253        mServiceMap.removeServiceByName(r.name, r.userId);
1254        mServiceMap.removeServiceByIntent(r.intent, r.userId);
1255        r.totalRestartCount = 0;
1256        unscheduleServiceRestartLocked(r);
1257
1258        // Also make sure it is not on the pending list.
1259        int N = mPendingServices.size();
1260        for (int i=0; i<N; i++) {
1261            if (mPendingServices.get(i) == r) {
1262                mPendingServices.remove(i);
1263                if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
1264                i--;
1265                N--;
1266            }
1267        }
1268
1269        r.cancelNotification();
1270        r.isForeground = false;
1271        r.foregroundId = 0;
1272        r.foregroundNoti = null;
1273
1274        // Clear start entries.
1275        r.clearDeliveredStartsLocked();
1276        r.pendingStarts.clear();
1277
1278        if (r.app != null) {
1279            synchronized (r.stats.getBatteryStats()) {
1280                r.stats.stopLaunchedLocked();
1281            }
1282            r.app.services.remove(r);
1283            if (r.app.thread != null) {
1284                try {
1285                    bumpServiceExecutingLocked(r, "stop");
1286                    mStoppingServices.add(r);
1287                    mAm.updateOomAdjLocked(r.app);
1288                    r.app.thread.scheduleStopService(r);
1289                } catch (Exception e) {
1290                    Slog.w(TAG, "Exception when stopping service "
1291                            + r.shortName, e);
1292                    serviceDoneExecutingLocked(r, true);
1293                }
1294                updateServiceForegroundLocked(r.app, false);
1295            } else {
1296                if (DEBUG_SERVICE) Slog.v(
1297                    TAG, "Removed service that has no process: " + r);
1298            }
1299        } else {
1300            if (DEBUG_SERVICE) Slog.v(
1301                TAG, "Removed service that is not running: " + r);
1302        }
1303
1304        if (r.bindings.size() > 0) {
1305            r.bindings.clear();
1306        }
1307
1308        if (r.restarter instanceof ServiceRestarter) {
1309           ((ServiceRestarter)r.restarter).setService(null);
1310        }
1311    }
1312
1313    void removeConnectionLocked(
1314        ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
1315        IBinder binder = c.conn.asBinder();
1316        AppBindRecord b = c.binding;
1317        ServiceRecord s = b.service;
1318        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
1319        if (clist != null) {
1320            clist.remove(c);
1321            if (clist.size() == 0) {
1322                s.connections.remove(binder);
1323            }
1324        }
1325        b.connections.remove(c);
1326        if (c.activity != null && c.activity != skipAct) {
1327            if (c.activity.connections != null) {
1328                c.activity.connections.remove(c);
1329            }
1330        }
1331        if (b.client != skipApp) {
1332            b.client.connections.remove(c);
1333            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
1334                b.client.updateHasAboveClientLocked();
1335            }
1336        }
1337        clist = mServiceConnections.get(binder);
1338        if (clist != null) {
1339            clist.remove(c);
1340            if (clist.size() == 0) {
1341                mServiceConnections.remove(binder);
1342            }
1343        }
1344
1345        if (b.connections.size() == 0) {
1346            b.intent.apps.remove(b.client);
1347        }
1348
1349        if (!c.serviceDead) {
1350            if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
1351                    + ": shouldUnbind=" + b.intent.hasBound);
1352            if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
1353                    && b.intent.hasBound) {
1354                try {
1355                    bumpServiceExecutingLocked(s, "unbind");
1356                    mAm.updateOomAdjLocked(s.app);
1357                    b.intent.hasBound = false;
1358                    // Assume the client doesn't want to know about a rebind;
1359                    // we will deal with that later if it asks for one.
1360                    b.intent.doRebind = false;
1361                    s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
1362                } catch (Exception e) {
1363                    Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
1364                    serviceDoneExecutingLocked(s, true);
1365                }
1366            }
1367
1368            if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
1369                bringDownServiceLocked(s, false);
1370            }
1371        }
1372    }
1373
1374    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
1375        boolean inStopping = mStoppingServices.contains(r);
1376        if (r != null) {
1377            if (type == 1) {
1378                // This is a call from a service start...  take care of
1379                // book-keeping.
1380                r.callStart = true;
1381                switch (res) {
1382                    case Service.START_STICKY_COMPATIBILITY:
1383                    case Service.START_STICKY: {
1384                        // We are done with the associated start arguments.
1385                        r.findDeliveredStart(startId, true);
1386                        // Don't stop if killed.
1387                        r.stopIfKilled = false;
1388                        break;
1389                    }
1390                    case Service.START_NOT_STICKY: {
1391                        // We are done with the associated start arguments.
1392                        r.findDeliveredStart(startId, true);
1393                        if (r.getLastStartId() == startId) {
1394                            // There is no more work, and this service
1395                            // doesn't want to hang around if killed.
1396                            r.stopIfKilled = true;
1397                        }
1398                        break;
1399                    }
1400                    case Service.START_REDELIVER_INTENT: {
1401                        // We'll keep this item until they explicitly
1402                        // call stop for it, but keep track of the fact
1403                        // that it was delivered.
1404                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
1405                        if (si != null) {
1406                            si.deliveryCount = 0;
1407                            si.doneExecutingCount++;
1408                            // Don't stop if killed.
1409                            r.stopIfKilled = true;
1410                        }
1411                        break;
1412                    }
1413                    case Service.START_TASK_REMOVED_COMPLETE: {
1414                        // Special processing for onTaskRemoved().  Don't
1415                        // impact normal onStartCommand() processing.
1416                        r.findDeliveredStart(startId, true);
1417                        break;
1418                    }
1419                    default:
1420                        throw new IllegalArgumentException(
1421                                "Unknown service start result: " + res);
1422                }
1423                if (res == Service.START_STICKY_COMPATIBILITY) {
1424                    r.callStart = false;
1425                }
1426            }
1427            if (DEBUG_MU)
1428                Slog.v(TAG_MU, "before serviceDontExecutingLocked, uid="
1429                        + Binder.getOrigCallingUid());
1430            final long origId = Binder.clearCallingIdentity();
1431            serviceDoneExecutingLocked(r, inStopping);
1432            Binder.restoreCallingIdentity(origId);
1433        } else {
1434            Slog.w(TAG, "Done executing unknown service from pid "
1435                    + Binder.getCallingPid());
1436        }
1437    }
1438
1439    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
1440        if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
1441                + ": nesting=" + r.executeNesting
1442                + ", inStopping=" + inStopping + ", app=" + r.app);
1443        else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
1444        r.executeNesting--;
1445        if (r.executeNesting <= 0 && r.app != null) {
1446            if (DEBUG_SERVICE) Slog.v(TAG,
1447                    "Nesting at 0 of " + r.shortName);
1448            r.app.executingServices.remove(r);
1449            if (r.app.executingServices.size() == 0) {
1450                if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
1451                        "No more executingServices of " + r.shortName);
1452                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
1453            }
1454            if (inStopping) {
1455                if (DEBUG_SERVICE) Slog.v(TAG,
1456                        "doneExecuting remove stopping " + r);
1457                mStoppingServices.remove(r);
1458                r.bindings.clear();
1459            }
1460            mAm.updateOomAdjLocked(r.app);
1461        }
1462    }
1463
1464    boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
1465        boolean didSomething = false;
1466        // Collect any services that are waiting for this process to come up.
1467        if (mPendingServices.size() > 0) {
1468            ServiceRecord sr = null;
1469            try {
1470                for (int i=0; i<mPendingServices.size(); i++) {
1471                    sr = mPendingServices.get(i);
1472                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
1473                            || !processName.equals(sr.processName))) {
1474                        continue;
1475                    }
1476
1477                    mPendingServices.remove(i);
1478                    i--;
1479                    realStartServiceLocked(sr, proc);
1480                    didSomething = true;
1481                }
1482            } catch (Exception e) {
1483                Slog.w(TAG, "Exception in new application when starting service "
1484                        + sr.shortName, e);
1485                throw e;
1486            }
1487        }
1488        // Also, if there are any services that are waiting to restart and
1489        // would run in this process, now is a good time to start them.  It would
1490        // be weird to bring up the process but arbitrarily not let the services
1491        // run at this point just because their restart time hasn't come up.
1492        if (mRestartingServices.size() > 0) {
1493            ServiceRecord sr = null;
1494            for (int i=0; i<mRestartingServices.size(); i++) {
1495                sr = mRestartingServices.get(i);
1496                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
1497                        || !processName.equals(sr.processName))) {
1498                    continue;
1499                }
1500                mAm.mHandler.removeCallbacks(sr.restarter);
1501                mAm.mHandler.post(sr.restarter);
1502            }
1503        }
1504        return didSomething;
1505    }
1506
1507    void processStartTimedOutLocked(ProcessRecord proc) {
1508        for (int i=0; i<mPendingServices.size(); i++) {
1509            ServiceRecord sr = mPendingServices.get(i);
1510            if ((proc.uid == sr.appInfo.uid
1511                    && proc.processName.equals(sr.processName))
1512                    || sr.isolatedProc == proc) {
1513                Slog.w(TAG, "Forcing bringing down service: " + sr);
1514                sr.isolatedProc = null;
1515                mPendingServices.remove(i);
1516                i--;
1517                bringDownServiceLocked(sr, true);
1518            }
1519        }
1520    }
1521
1522    boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
1523        boolean didSomething = false;
1524        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
1525        for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
1526            if ((name == null || service.packageName.equals(name))
1527                    && (service.app == null || evenPersistent || !service.app.persistent)) {
1528                if (!doit) {
1529                    return true;
1530                }
1531                didSomething = true;
1532                Slog.i(TAG, "  Force stopping service " + service);
1533                if (service.app != null) {
1534                    service.app.removed = true;
1535                }
1536                service.app = null;
1537                service.isolatedProc = null;
1538                services.add(service);
1539            }
1540        }
1541
1542        int N = services.size();
1543        for (int i=0; i<N; i++) {
1544            bringDownServiceLocked(services.get(i), true);
1545        }
1546        return didSomething;
1547    }
1548
1549    void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
1550        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
1551        for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
1552            if (sr.packageName.equals(component.getPackageName())) {
1553                services.add(sr);
1554            }
1555        }
1556
1557        // Take care of any running services associated with the app.
1558        for (int i=0; i<services.size(); i++) {
1559            ServiceRecord sr = services.get(i);
1560            if (sr.startRequested) {
1561                if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
1562                    Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
1563                    stopServiceLocked(sr);
1564                } else {
1565                    sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
1566                            sr.makeNextStartId(), baseIntent, null));
1567                    if (sr.app != null && sr.app.thread != null) {
1568                        sendServiceArgsLocked(sr, false);
1569                    }
1570                }
1571            }
1572        }
1573    }
1574
1575    final void killServicesLocked(ProcessRecord app,
1576            boolean allowRestart) {
1577        // Report disconnected services.
1578        if (false) {
1579            // XXX we are letting the client link to the service for
1580            // death notifications.
1581            if (app.services.size() > 0) {
1582                Iterator<ServiceRecord> it = app.services.iterator();
1583                while (it.hasNext()) {
1584                    ServiceRecord r = it.next();
1585                    if (r.connections.size() > 0) {
1586                        Iterator<ArrayList<ConnectionRecord>> jt
1587                                = r.connections.values().iterator();
1588                        while (jt.hasNext()) {
1589                            ArrayList<ConnectionRecord> cl = jt.next();
1590                            for (int i=0; i<cl.size(); i++) {
1591                                ConnectionRecord c = cl.get(i);
1592                                if (c.binding.client != app) {
1593                                    try {
1594                                        //c.conn.connected(r.className, null);
1595                                    } catch (Exception e) {
1596                                        // todo: this should be asynchronous!
1597                                        Slog.w(TAG, "Exception thrown disconnected servce "
1598                                              + r.shortName
1599                                              + " from app " + app.processName, e);
1600                                    }
1601                                }
1602                            }
1603                        }
1604                    }
1605                }
1606            }
1607        }
1608
1609        // Clean up any connections this application has to other services.
1610        if (app.connections.size() > 0) {
1611            Iterator<ConnectionRecord> it = app.connections.iterator();
1612            while (it.hasNext()) {
1613                ConnectionRecord r = it.next();
1614                removeConnectionLocked(r, app, null);
1615            }
1616        }
1617        app.connections.clear();
1618
1619        if (app.services.size() != 0) {
1620            // Any services running in the application need to be placed
1621            // back in the pending list.
1622            Iterator<ServiceRecord> it = app.services.iterator();
1623            while (it.hasNext()) {
1624                ServiceRecord sr = it.next();
1625                synchronized (sr.stats.getBatteryStats()) {
1626                    sr.stats.stopLaunchedLocked();
1627                }
1628                sr.app = null;
1629                sr.isolatedProc = null;
1630                sr.executeNesting = 0;
1631                if (mStoppingServices.remove(sr)) {
1632                    if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
1633                }
1634
1635                boolean hasClients = sr.bindings.size() > 0;
1636                if (hasClients) {
1637                    Iterator<IntentBindRecord> bindings
1638                            = sr.bindings.values().iterator();
1639                    while (bindings.hasNext()) {
1640                        IntentBindRecord b = bindings.next();
1641                        if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
1642                                + ": shouldUnbind=" + b.hasBound);
1643                        b.binder = null;
1644                        b.requested = b.received = b.hasBound = false;
1645                    }
1646                }
1647
1648                if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
1649                        &ApplicationInfo.FLAG_PERSISTENT) == 0) {
1650                    Slog.w(TAG, "Service crashed " + sr.crashCount
1651                            + " times, stopping: " + sr);
1652                    EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
1653                            sr.crashCount, sr.shortName, app.pid);
1654                    bringDownServiceLocked(sr, true);
1655                } else if (!allowRestart) {
1656                    bringDownServiceLocked(sr, true);
1657                } else {
1658                    boolean canceled = scheduleServiceRestartLocked(sr, true);
1659
1660                    // Should the service remain running?  Note that in the
1661                    // extreme case of so many attempts to deliver a command
1662                    // that it failed we also will stop it here.
1663                    if (sr.startRequested && (sr.stopIfKilled || canceled)) {
1664                        if (sr.pendingStarts.size() == 0) {
1665                            sr.startRequested = false;
1666                            if (!hasClients) {
1667                                // Whoops, no reason to restart!
1668                                bringDownServiceLocked(sr, true);
1669                            }
1670                        }
1671                    }
1672                }
1673            }
1674
1675            if (!allowRestart) {
1676                app.services.clear();
1677            }
1678        }
1679
1680        // Make sure we have no more records on the stopping list.
1681        int i = mStoppingServices.size();
1682        while (i > 0) {
1683            i--;
1684            ServiceRecord sr = mStoppingServices.get(i);
1685            if (sr.app == app) {
1686                mStoppingServices.remove(i);
1687                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
1688            }
1689        }
1690
1691        app.executingServices.clear();
1692    }
1693
1694    ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
1695        ActivityManager.RunningServiceInfo info =
1696            new ActivityManager.RunningServiceInfo();
1697        info.service = r.name;
1698        if (r.app != null) {
1699            info.pid = r.app.pid;
1700        }
1701        info.uid = r.appInfo.uid;
1702        info.process = r.processName;
1703        info.foreground = r.isForeground;
1704        info.activeSince = r.createTime;
1705        info.started = r.startRequested;
1706        info.clientCount = r.connections.size();
1707        info.crashCount = r.crashCount;
1708        info.lastActivityTime = r.lastActivity;
1709        if (r.isForeground) {
1710            info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
1711        }
1712        if (r.startRequested) {
1713            info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
1714        }
1715        if (r.app != null && r.app.pid == ActivityManagerService.MY_PID) {
1716            info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
1717        }
1718        if (r.app != null && r.app.persistent) {
1719            info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
1720        }
1721
1722        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
1723            for (int i=0; i<connl.size(); i++) {
1724                ConnectionRecord conn = connl.get(i);
1725                if (conn.clientLabel != 0) {
1726                    info.clientPackage = conn.binding.client.info.packageName;
1727                    info.clientLabel = conn.clientLabel;
1728                    return info;
1729                }
1730            }
1731        }
1732        return info;
1733    }
1734
1735    List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum,
1736            int flags) {
1737        ArrayList<ActivityManager.RunningServiceInfo> res
1738                = new ArrayList<ActivityManager.RunningServiceInfo>();
1739
1740        final int uid = Binder.getCallingUid();
1741        final long ident = Binder.clearCallingIdentity();
1742        try {
1743            if (ActivityManager.checkUidPermission(
1744                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1745                    uid) == PackageManager.PERMISSION_GRANTED) {
1746                List<UserInfo> users = mAm.getUserManager().getUsers();
1747                for (int ui=0; ui<users.size() && res.size() < maxNum; ui++) {
1748                    final UserInfo user = users.get(ui);
1749                    if (mServiceMap.getAllServices(user.id).size() > 0) {
1750                        Iterator<ServiceRecord> it = mServiceMap.getAllServices(
1751                                user.id).iterator();
1752                        while (it.hasNext() && res.size() < maxNum) {
1753                            res.add(makeRunningServiceInfoLocked(it.next()));
1754                        }
1755                    }
1756                }
1757
1758                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
1759                    ServiceRecord r = mRestartingServices.get(i);
1760                    ActivityManager.RunningServiceInfo info =
1761                            makeRunningServiceInfoLocked(r);
1762                    info.restarting = r.nextRestartTime;
1763                    res.add(info);
1764                }
1765            } else {
1766                int userId = UserHandle.getUserId(uid);
1767                if (mServiceMap.getAllServices(userId).size() > 0) {
1768                    Iterator<ServiceRecord> it
1769                            = mServiceMap.getAllServices(userId).iterator();
1770                    while (it.hasNext() && res.size() < maxNum) {
1771                        res.add(makeRunningServiceInfoLocked(it.next()));
1772                    }
1773                }
1774
1775                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
1776                    ServiceRecord r = mRestartingServices.get(i);
1777                    if (r.userId == userId) {
1778                        ActivityManager.RunningServiceInfo info =
1779                                makeRunningServiceInfoLocked(r);
1780                        info.restarting = r.nextRestartTime;
1781                        res.add(info);
1782                    }
1783                }
1784            }
1785        } finally {
1786            Binder.restoreCallingIdentity(ident);
1787        }
1788
1789        return res;
1790    }
1791
1792    public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
1793        int userId = UserHandle.getUserId(Binder.getCallingUid());
1794        ServiceRecord r = mServiceMap.getServiceByName(name, userId);
1795        if (r != null) {
1796            for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
1797                for (int i=0; i<conn.size(); i++) {
1798                    if (conn.get(i).clientIntent != null) {
1799                        return conn.get(i).clientIntent;
1800                    }
1801                }
1802            }
1803        }
1804        return null;
1805    }
1806
1807    void serviceTimeout(ProcessRecord proc) {
1808        String anrMessage = null;
1809
1810        synchronized(this) {
1811            if (proc.executingServices.size() == 0 || proc.thread == null) {
1812                return;
1813            }
1814            long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
1815            Iterator<ServiceRecord> it = proc.executingServices.iterator();
1816            ServiceRecord timeout = null;
1817            long nextTime = 0;
1818            while (it.hasNext()) {
1819                ServiceRecord sr = it.next();
1820                if (sr.executingStart < maxTime) {
1821                    timeout = sr;
1822                    break;
1823                }
1824                if (sr.executingStart > nextTime) {
1825                    nextTime = sr.executingStart;
1826                }
1827            }
1828            if (timeout != null && mAm.mLruProcesses.contains(proc)) {
1829                Slog.w(TAG, "Timeout executing service: " + timeout);
1830                anrMessage = "Executing service " + timeout.shortName;
1831            } else {
1832                Message msg = mAm.mHandler.obtainMessage(
1833                        ActivityManagerService.SERVICE_TIMEOUT_MSG);
1834                msg.obj = proc;
1835                mAm.mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
1836            }
1837        }
1838
1839        if (anrMessage != null) {
1840            mAm.appNotResponding(proc, null, null, anrMessage);
1841        }
1842    }
1843
1844    /**
1845     * Prints a list of ServiceRecords (dumpsys activity services)
1846     */
1847    boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
1848            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
1849        boolean needSep = false;
1850
1851        ItemMatcher matcher = new ItemMatcher();
1852        matcher.build(args, opti);
1853
1854        pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
1855        try {
1856            List<UserInfo> users = mAm.getUserManager().getUsers();
1857            for (int ui=0; ui<users.size(); ui++) {
1858                final UserInfo user = users.get(ui);
1859                if (mServiceMap.getAllServices(user.id).size() > 0) {
1860                    boolean printed = false;
1861                    long nowReal = SystemClock.elapsedRealtime();
1862                    Iterator<ServiceRecord> it = mServiceMap.getAllServices(
1863                            user.id).iterator();
1864                    needSep = false;
1865                    while (it.hasNext()) {
1866                        ServiceRecord r = it.next();
1867                        if (!matcher.match(r, r.name)) {
1868                            continue;
1869                        }
1870                        if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1871                            continue;
1872                        }
1873                        if (!printed) {
1874                            if (ui > 0) {
1875                                pw.println();
1876                            }
1877                            pw.println("  User " + user.id + " active services:");
1878                            printed = true;
1879                        }
1880                        if (needSep) {
1881                            pw.println();
1882                        }
1883                        pw.print("  * ");
1884                        pw.println(r);
1885                        if (dumpAll) {
1886                            r.dump(pw, "    ");
1887                            needSep = true;
1888                        } else {
1889                            pw.print("    app=");
1890                            pw.println(r.app);
1891                            pw.print("    created=");
1892                            TimeUtils.formatDuration(r.createTime, nowReal, pw);
1893                            pw.print(" started=");
1894                            pw.print(r.startRequested);
1895                            pw.print(" connections=");
1896                            pw.println(r.connections.size());
1897                            if (r.connections.size() > 0) {
1898                                pw.println("    Connections:");
1899                                for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
1900                                    for (int i = 0; i < clist.size(); i++) {
1901                                        ConnectionRecord conn = clist.get(i);
1902                                        pw.print("      ");
1903                                        pw.print(conn.binding.intent.intent.getIntent()
1904                                                .toShortString(false, false, false, false));
1905                                        pw.print(" -> ");
1906                                        ProcessRecord proc = conn.binding.client;
1907                                        pw.println(proc != null ? proc.toShortString() : "null");
1908                                    }
1909                                }
1910                            }
1911                        }
1912                        if (dumpClient && r.app != null && r.app.thread != null) {
1913                            pw.println("    Client:");
1914                            pw.flush();
1915                            try {
1916                                TransferPipe tp = new TransferPipe();
1917                                try {
1918                                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
1919                                            r, args);
1920                                    tp.setBufferPrefix("      ");
1921                                    // Short timeout, since blocking here can
1922                                    // deadlock with the application.
1923                                    tp.go(fd, 2000);
1924                                } finally {
1925                                    tp.kill();
1926                                }
1927                            } catch (IOException e) {
1928                                pw.println("      Failure while dumping the service: " + e);
1929                            } catch (RemoteException e) {
1930                                pw.println("      Got a RemoteException while dumping the service");
1931                            }
1932                            needSep = true;
1933                        }
1934                    }
1935                    needSep = printed;
1936                }
1937            }
1938        } catch (Exception e) {
1939            Log.w(TAG, "Exception in dumpServicesLocked: " + e);
1940        }
1941
1942        if (mPendingServices.size() > 0) {
1943            boolean printed = false;
1944            for (int i=0; i<mPendingServices.size(); i++) {
1945                ServiceRecord r = mPendingServices.get(i);
1946                if (!matcher.match(r, r.name)) {
1947                    continue;
1948                }
1949                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1950                    continue;
1951                }
1952                if (!printed) {
1953                    if (needSep) pw.println(" ");
1954                    needSep = true;
1955                    pw.println("  Pending services:");
1956                    printed = true;
1957                }
1958                pw.print("  * Pending "); pw.println(r);
1959                r.dump(pw, "    ");
1960            }
1961            needSep = true;
1962        }
1963
1964        if (mRestartingServices.size() > 0) {
1965            boolean printed = false;
1966            for (int i=0; i<mRestartingServices.size(); i++) {
1967                ServiceRecord r = mRestartingServices.get(i);
1968                if (!matcher.match(r, r.name)) {
1969                    continue;
1970                }
1971                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1972                    continue;
1973                }
1974                if (!printed) {
1975                    if (needSep) pw.println(" ");
1976                    needSep = true;
1977                    pw.println("  Restarting services:");
1978                    printed = true;
1979                }
1980                pw.print("  * Restarting "); pw.println(r);
1981                r.dump(pw, "    ");
1982            }
1983            needSep = true;
1984        }
1985
1986        if (mStoppingServices.size() > 0) {
1987            boolean printed = false;
1988            for (int i=0; i<mStoppingServices.size(); i++) {
1989                ServiceRecord r = mStoppingServices.get(i);
1990                if (!matcher.match(r, r.name)) {
1991                    continue;
1992                }
1993                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1994                    continue;
1995                }
1996                if (!printed) {
1997                    if (needSep) pw.println(" ");
1998                    needSep = true;
1999                    pw.println("  Stopping services:");
2000                    printed = true;
2001                }
2002                pw.print("  * Stopping "); pw.println(r);
2003                r.dump(pw, "    ");
2004            }
2005            needSep = true;
2006        }
2007
2008        if (dumpAll) {
2009            if (mServiceConnections.size() > 0) {
2010                boolean printed = false;
2011                Iterator<ArrayList<ConnectionRecord>> it
2012                        = mServiceConnections.values().iterator();
2013                while (it.hasNext()) {
2014                    ArrayList<ConnectionRecord> r = it.next();
2015                    for (int i=0; i<r.size(); i++) {
2016                        ConnectionRecord cr = r.get(i);
2017                        if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
2018                            continue;
2019                        }
2020                        if (dumpPackage != null && (cr.binding.client == null
2021                                || !dumpPackage.equals(cr.binding.client.info.packageName))) {
2022                            continue;
2023                        }
2024                        if (!printed) {
2025                            if (needSep) pw.println(" ");
2026                            needSep = true;
2027                            pw.println("  Connection bindings to services:");
2028                            printed = true;
2029                        }
2030                        pw.print("  * "); pw.println(cr);
2031                        cr.dump(pw, "    ");
2032                    }
2033                }
2034                needSep = true;
2035            }
2036        }
2037
2038        return needSep;
2039    }
2040
2041    /**
2042     * There are three ways to call this:
2043     *  - no service specified: dump all the services
2044     *  - a flattened component name that matched an existing service was specified as the
2045     *    first arg: dump that one service
2046     *  - the first arg isn't the flattened component name of an existing service:
2047     *    dump all services whose component contains the first arg as a substring
2048     */
2049    protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
2050            int opti, boolean dumpAll) {
2051        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
2052
2053        List<UserInfo> users = mAm.getUserManager().getUsers();
2054        if ("all".equals(name)) {
2055            synchronized (this) {
2056                for (UserInfo user : users) {
2057                    for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
2058                        services.add(r1);
2059                    }
2060                }
2061            }
2062        } else {
2063            ComponentName componentName = name != null
2064                    ? ComponentName.unflattenFromString(name) : null;
2065            int objectId = 0;
2066            if (componentName == null) {
2067                // Not a '/' separated full component name; maybe an object ID?
2068                try {
2069                    objectId = Integer.parseInt(name, 16);
2070                    name = null;
2071                    componentName = null;
2072                } catch (RuntimeException e) {
2073                }
2074            }
2075
2076            synchronized (this) {
2077                for (UserInfo user : users) {
2078                    for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
2079                        if (componentName != null) {
2080                            if (r1.name.equals(componentName)) {
2081                                services.add(r1);
2082                            }
2083                        } else if (name != null) {
2084                            if (r1.name.flattenToString().contains(name)) {
2085                                services.add(r1);
2086                            }
2087                        } else if (System.identityHashCode(r1) == objectId) {
2088                            services.add(r1);
2089                        }
2090                    }
2091                }
2092            }
2093        }
2094
2095        if (services.size() <= 0) {
2096            return false;
2097        }
2098
2099        boolean needSep = false;
2100        for (int i=0; i<services.size(); i++) {
2101            if (needSep) {
2102                pw.println();
2103            }
2104            needSep = true;
2105            dumpService("", fd, pw, services.get(i), args, dumpAll);
2106        }
2107        return true;
2108    }
2109
2110    /**
2111     * Invokes IApplicationThread.dumpService() on the thread of the specified service if
2112     * there is a thread associated with the service.
2113     */
2114    private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
2115            final ServiceRecord r, String[] args, boolean dumpAll) {
2116        String innerPrefix = prefix + "  ";
2117        synchronized (this) {
2118            pw.print(prefix); pw.print("SERVICE ");
2119                    pw.print(r.shortName); pw.print(" ");
2120                    pw.print(Integer.toHexString(System.identityHashCode(r)));
2121                    pw.print(" pid=");
2122                    if (r.app != null) pw.println(r.app.pid);
2123                    else pw.println("(not running)");
2124            if (dumpAll) {
2125                r.dump(pw, innerPrefix);
2126            }
2127        }
2128        if (r.app != null && r.app.thread != null) {
2129            pw.print(prefix); pw.println("  Client:");
2130            pw.flush();
2131            try {
2132                TransferPipe tp = new TransferPipe();
2133                try {
2134                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
2135                    tp.setBufferPrefix(prefix + "    ");
2136                    tp.go(fd);
2137                } finally {
2138                    tp.kill();
2139                }
2140            } catch (IOException e) {
2141                pw.println(prefix + "    Failure while dumping the service: " + e);
2142            } catch (RemoteException e) {
2143                pw.println(prefix + "    Got a RemoteException while dumping the service");
2144            }
2145        }
2146    }
2147
2148}
2149