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