blob: 5c24e6781402d0ba110a77416f77f0e32d4b67e3 [file] [log] [blame]
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001/*
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;
Dianne Hackborn599db5c2012-08-03 19:28:48 -070047import android.os.Binder;
48import android.os.IBinder;
49import android.os.Message;
50import android.os.Process;
51import android.os.RemoteException;
52import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070053import android.os.UserHandle;
Dianne Hackborn599db5c2012-08-03 19:28:48 -070054import 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) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700187 HashMap<ComponentName, ServiceRecord> map = mServicesByNamePerUser.get(callingUser);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700188 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) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700197 HashMap<Intent.FilterComparison, ServiceRecord> map
198 = mServicesByIntentPerUser.get(callingUser);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700199 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,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700213 int callingPid, int callingUid, int userId) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700214 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,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700229 callingPid, callingUid, userId, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700230 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 }
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700251 String error = bringUpServiceLocked(r, service.getFlags(), false);
252 if (error != null) {
253 return new ComponentName("!!", error);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700254 }
255 return r.name;
256 }
257
258 private void stopServiceLocked(ServiceRecord service) {
259 synchronized (service.stats.getBatteryStats()) {
260 service.stats.stopRunningLocked();
261 }
262 service.startRequested = false;
263 service.callStart = false;
264 bringDownServiceLocked(service, false);
265 }
266
267 int stopServiceLocked(IApplicationThread caller, Intent service,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700268 String resolvedType, int userId) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700269 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
270 + " type=" + resolvedType);
271
272 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
273 if (caller != null && callerApp == null) {
274 throw new SecurityException(
275 "Unable to find app for caller " + caller
276 + " (pid=" + Binder.getCallingPid()
277 + ") when stopping service " + service);
278 }
279
280 // If this service is active, make sure it is stopped.
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700281 ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700282 Binder.getCallingPid(), Binder.getCallingUid(), userId, false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700283 if (r != null) {
284 if (r.record != null) {
285 final long origId = Binder.clearCallingIdentity();
286 try {
287 stopServiceLocked(r.record);
288 } finally {
289 Binder.restoreCallingIdentity(origId);
290 }
291 return 1;
292 }
293 return -1;
294 }
295
296 return 0;
297 }
298
299 IBinder peekServiceLocked(Intent service, String resolvedType) {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700300 ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
301 Binder.getCallingPid(), Binder.getCallingUid(),
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700302 UserHandle.getCallingUserId(), false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700303
304 IBinder ret = null;
305 if (r != null) {
306 // r.record is null if findServiceLocked() failed the caller permission check
307 if (r.record == null) {
308 throw new SecurityException(
309 "Permission Denial: Accessing service " + r.record.name
310 + " from pid=" + Binder.getCallingPid()
311 + ", uid=" + Binder.getCallingUid()
312 + " requires " + r.permission);
313 }
314 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
315 if (ib != null) {
316 ret = ib.binder;
317 }
318 }
319
320 return ret;
321 }
322
323 boolean stopServiceTokenLocked(ComponentName className, IBinder token,
324 int startId) {
325 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
326 + " " + token + " startId=" + startId);
Dianne Hackborn41203752012-08-31 14:05:51 -0700327 ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700328 if (r != null) {
329 if (startId >= 0) {
330 // Asked to only stop if done with all work. Note that
331 // to avoid leaks, we will take this as dropping all
332 // start items up to and including this one.
333 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
334 if (si != null) {
335 while (r.deliveredStarts.size() > 0) {
336 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
337 cur.removeUriPermissionsLocked();
338 if (cur == si) {
339 break;
340 }
341 }
342 }
343
344 if (r.getLastStartId() != startId) {
345 return false;
346 }
347
348 if (r.deliveredStarts.size() > 0) {
349 Slog.w(TAG, "stopServiceToken startId " + startId
350 + " is last, but have " + r.deliveredStarts.size()
351 + " remaining args");
352 }
353 }
354
355 synchronized (r.stats.getBatteryStats()) {
356 r.stats.stopRunningLocked();
357 r.startRequested = false;
358 r.callStart = false;
359 }
360 final long origId = Binder.clearCallingIdentity();
361 bringDownServiceLocked(r, false);
362 Binder.restoreCallingIdentity(origId);
363 return true;
364 }
365 return false;
366 }
367
368 public void setServiceForegroundLocked(ComponentName className, IBinder token,
369 int id, Notification notification, boolean removeNotification) {
Dianne Hackborn41203752012-08-31 14:05:51 -0700370 final int userId = UserHandle.getCallingUserId();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700371 final long origId = Binder.clearCallingIdentity();
372 try {
Dianne Hackborn41203752012-08-31 14:05:51 -0700373 ServiceRecord r = findServiceLocked(className, token, userId);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700374 if (r != null) {
375 if (id != 0) {
376 if (notification == null) {
377 throw new IllegalArgumentException("null notification");
378 }
379 if (r.foregroundId != id) {
380 r.cancelNotification();
381 r.foregroundId = id;
382 }
383 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
384 r.foregroundNoti = notification;
385 r.isForeground = true;
386 r.postNotification();
387 if (r.app != null) {
388 updateServiceForegroundLocked(r.app, true);
389 }
390 } else {
391 if (r.isForeground) {
392 r.isForeground = false;
393 if (r.app != null) {
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700394 mAm.updateLruProcessLocked(r.app, false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700395 updateServiceForegroundLocked(r.app, true);
396 }
397 }
398 if (removeNotification) {
399 r.cancelNotification();
400 r.foregroundId = 0;
401 r.foregroundNoti = null;
402 }
403 }
404 }
405 } finally {
406 Binder.restoreCallingIdentity(origId);
407 }
408 }
409
410 private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
411 boolean anyForeground = false;
412 for (ServiceRecord sr : proc.services) {
413 if (sr.isForeground) {
414 anyForeground = true;
415 break;
416 }
417 }
418 if (anyForeground != proc.foregroundServices) {
419 proc.foregroundServices = anyForeground;
420 if (oomAdj) {
421 mAm.updateOomAdjLocked();
422 }
423 }
424 }
425
426 int bindServiceLocked(IApplicationThread caller, IBinder token,
427 Intent service, String resolvedType,
428 IServiceConnection connection, int flags, int userId) {
429 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
430 + " type=" + resolvedType + " conn=" + connection.asBinder()
431 + " flags=0x" + Integer.toHexString(flags));
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700432 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
433 if (callerApp == null) {
434 throw new SecurityException(
435 "Unable to find app for caller " + caller
436 + " (pid=" + Binder.getCallingPid()
437 + ") when binding service " + service);
438 }
439
440 ActivityRecord activity = null;
441 if (token != null) {
442 activity = mAm.mMainStack.isInStackLocked(token);
443 if (activity == null) {
444 Slog.w(TAG, "Binding with unknown activity: " + token);
445 return 0;
446 }
447 }
448
449 int clientLabel = 0;
450 PendingIntent clientIntent = null;
451
452 if (callerApp.info.uid == Process.SYSTEM_UID) {
453 // Hacky kind of thing -- allow system stuff to tell us
454 // what they are, so we can report this elsewhere for
455 // others to know why certain services are running.
456 try {
457 clientIntent = (PendingIntent)service.getParcelableExtra(
458 Intent.EXTRA_CLIENT_INTENT);
459 } catch (RuntimeException e) {
460 }
461 if (clientIntent != null) {
462 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
463 if (clientLabel != 0) {
464 // There are no useful extras in the intent, trash them.
465 // System code calling with this stuff just needs to know
466 // this will happen.
467 service = service.cloneFilter();
468 }
469 }
470 }
471
472 ServiceLookupResult res =
473 retrieveServiceLocked(service, resolvedType,
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700474 Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700475 if (res == null) {
476 return 0;
477 }
478 if (res.record == null) {
479 return -1;
480 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700481 ServiceRecord s = res.record;
482
483 final long origId = Binder.clearCallingIdentity();
484
485 try {
486 if (unscheduleServiceRestartLocked(s)) {
487 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
488 + s);
489 }
490
491 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
492 ConnectionRecord c = new ConnectionRecord(b, activity,
493 connection, flags, clientLabel, clientIntent);
494
495 IBinder binder = connection.asBinder();
496 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
497 if (clist == null) {
498 clist = new ArrayList<ConnectionRecord>();
499 s.connections.put(binder, clist);
500 }
501 clist.add(c);
502 b.connections.add(c);
503 if (activity != null) {
504 if (activity.connections == null) {
505 activity.connections = new HashSet<ConnectionRecord>();
506 }
507 activity.connections.add(c);
508 }
509 b.client.connections.add(c);
510 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
511 b.client.hasAboveClient = true;
512 }
513 clist = mServiceConnections.get(binder);
514 if (clist == null) {
515 clist = new ArrayList<ConnectionRecord>();
516 mServiceConnections.put(binder, clist);
517 }
518 clist.add(c);
519
520 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
521 s.lastActivity = SystemClock.uptimeMillis();
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700522 if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700523 return 0;
524 }
525 }
526
527 if (s.app != null) {
528 // This could have made the service more important.
529 mAm.updateOomAdjLocked(s.app);
530 }
531
532 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
533 + ": received=" + b.intent.received
534 + " apps=" + b.intent.apps.size()
535 + " doRebind=" + b.intent.doRebind);
536
537 if (s.app != null && b.intent.received) {
538 // Service is already running, so we can immediately
539 // publish the connection.
540 try {
541 c.conn.connected(s.name, b.intent.binder);
542 } catch (Exception e) {
543 Slog.w(TAG, "Failure sending service " + s.shortName
544 + " to connection " + c.conn.asBinder()
545 + " (in " + c.binding.client.processName + ")", e);
546 }
547
548 // If this is the first app connected back to this binding,
549 // and the service had previously asked to be told when
550 // rebound, then do so.
551 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
552 requestServiceBindingLocked(s, b.intent, true);
553 }
554 } else if (!b.intent.requested) {
555 requestServiceBindingLocked(s, b.intent, false);
556 }
557 } finally {
558 Binder.restoreCallingIdentity(origId);
559 }
560
561 return 1;
562 }
563
564 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
565 final long origId = Binder.clearCallingIdentity();
566 try {
567 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
568 + " " + intent + ": " + service);
569 if (r != null) {
570 Intent.FilterComparison filter
571 = new Intent.FilterComparison(intent);
572 IntentBindRecord b = r.bindings.get(filter);
573 if (b != null && !b.received) {
574 b.binder = service;
575 b.requested = true;
576 b.received = true;
577 if (r.connections.size() > 0) {
578 Iterator<ArrayList<ConnectionRecord>> it
579 = r.connections.values().iterator();
580 while (it.hasNext()) {
581 ArrayList<ConnectionRecord> clist = it.next();
582 for (int i=0; i<clist.size(); i++) {
583 ConnectionRecord c = clist.get(i);
584 if (!filter.equals(c.binding.intent.intent)) {
585 if (DEBUG_SERVICE) Slog.v(
586 TAG, "Not publishing to: " + c);
587 if (DEBUG_SERVICE) Slog.v(
588 TAG, "Bound intent: " + c.binding.intent.intent);
589 if (DEBUG_SERVICE) Slog.v(
590 TAG, "Published intent: " + intent);
591 continue;
592 }
593 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
594 try {
595 c.conn.connected(r.name, service);
596 } catch (Exception e) {
597 Slog.w(TAG, "Failure sending service " + r.name +
598 " to connection " + c.conn.asBinder() +
599 " (in " + c.binding.client.processName + ")", e);
600 }
601 }
602 }
603 }
604 }
605
606 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
607 }
608 } finally {
609 Binder.restoreCallingIdentity(origId);
610 }
611 }
612
613 boolean unbindServiceLocked(IServiceConnection connection) {
614 IBinder binder = connection.asBinder();
615 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
616 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
617 if (clist == null) {
618 Slog.w(TAG, "Unbind failed: could not find connection for "
619 + connection.asBinder());
620 return false;
621 }
622
623 final long origId = Binder.clearCallingIdentity();
624 try {
625 while (clist.size() > 0) {
626 ConnectionRecord r = clist.get(0);
627 removeConnectionLocked(r, null, null);
628
629 if (r.binding.service.app != null) {
630 // This could have made the service less important.
631 mAm.updateOomAdjLocked(r.binding.service.app);
632 }
633 }
634 } finally {
635 Binder.restoreCallingIdentity(origId);
636 }
637
638 return true;
639 }
640
641 void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) {
642 final long origId = Binder.clearCallingIdentity();
643 try {
644 if (r != null) {
645 Intent.FilterComparison filter
646 = new Intent.FilterComparison(intent);
647 IntentBindRecord b = r.bindings.get(filter);
648 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
649 + " at " + b + ": apps="
650 + (b != null ? b.apps.size() : 0));
651
652 boolean inStopping = mStoppingServices.contains(r);
653 if (b != null) {
654 if (b.apps.size() > 0 && !inStopping) {
655 // Applications have already bound since the last
656 // unbind, so just rebind right here.
657 requestServiceBindingLocked(r, b, true);
658 } else {
659 // Note to tell the service the next time there is
660 // a new client.
661 b.doRebind = true;
662 }
663 }
664
665 serviceDoneExecutingLocked(r, inStopping);
666 }
667 } finally {
668 Binder.restoreCallingIdentity(origId);
669 }
670 }
671
672 private final ServiceRecord findServiceLocked(ComponentName name,
Dianne Hackborn41203752012-08-31 14:05:51 -0700673 IBinder token, int userId) {
674 ServiceRecord r = mServiceMap.getServiceByName(name, userId);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700675 return r == token ? r : null;
676 }
677
678 private final class ServiceLookupResult {
679 final ServiceRecord record;
680 final String permission;
681
682 ServiceLookupResult(ServiceRecord _record, String _permission) {
683 record = _record;
684 permission = _permission;
685 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700686 }
687
688 private class ServiceRestarter implements Runnable {
689 private ServiceRecord mService;
690
691 void setService(ServiceRecord service) {
692 mService = service;
693 }
694
695 public void run() {
696 synchronized(mAm) {
697 performServiceRestartLocked(mService);
698 }
699 }
700 }
701
702 private ServiceLookupResult retrieveServiceLocked(Intent service,
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700703 String resolvedType, int callingPid, int callingUid, int userId,
704 boolean createIfNeeded) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700705 ServiceRecord r = null;
706 if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
707 + " type=" + resolvedType + " callingUid=" + callingUid);
708
Dianne Hackborn139748f2012-09-24 11:36:57 -0700709 userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700710 false, true, "service", null);
711
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700712 if (service.getComponent() != null) {
713 r = mServiceMap.getServiceByName(service.getComponent(), userId);
714 }
715 if (r == null) {
716 Intent.FilterComparison filter = new Intent.FilterComparison(service);
717 r = mServiceMap.getServiceByIntent(filter, userId);
718 }
719 if (r == null) {
720 try {
721 ResolveInfo rInfo =
722 AppGlobals.getPackageManager().resolveService(
723 service, resolvedType,
724 ActivityManagerService.STOCK_PM_FLAGS, userId);
725 ServiceInfo sInfo =
726 rInfo != null ? rInfo.serviceInfo : null;
727 if (sInfo == null) {
Amith Yamasani2b914652012-08-27 12:04:40 -0700728 Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700729 ": not found");
730 return null;
731 }
732 ComponentName name = new ComponentName(
733 sInfo.applicationInfo.packageName, sInfo.name);
734 if (userId > 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700735 if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
736 sInfo.name, sInfo.flags)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700737 userId = 0;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700738 }
739 sInfo = new ServiceInfo(sInfo);
740 sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
741 }
742 r = mServiceMap.getServiceByName(name, userId);
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700743 if (r == null && createIfNeeded) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700744 Intent.FilterComparison filter = new Intent.FilterComparison(
745 service.cloneFilter());
746 ServiceRestarter res = new ServiceRestarter();
747 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
748 BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
749 synchronized (stats) {
750 ss = stats.getServiceStatsLocked(
751 sInfo.applicationInfo.uid, sInfo.packageName,
752 sInfo.name);
753 }
754 r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);
755 res.setService(r);
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700756 mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
757 mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700758
759 // Make sure this component isn't in the pending list.
760 int N = mPendingServices.size();
761 for (int i=0; i<N; i++) {
762 ServiceRecord pr = mPendingServices.get(i);
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700763 if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
764 && pr.name.equals(name)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700765 mPendingServices.remove(i);
766 i--;
767 N--;
768 }
769 }
770 }
771 } catch (RemoteException ex) {
772 // pm is in same process, this will never happen.
773 }
774 }
775 if (r != null) {
776 if (mAm.checkComponentPermission(r.permission,
777 callingPid, callingUid, r.appInfo.uid, r.exported)
778 != PackageManager.PERMISSION_GRANTED) {
779 if (!r.exported) {
780 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
781 + " from pid=" + callingPid
782 + ", uid=" + callingUid
783 + " that is not exported from uid " + r.appInfo.uid);
784 return new ServiceLookupResult(null, "not exported from uid "
785 + r.appInfo.uid);
786 }
787 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
788 + " from pid=" + callingPid
789 + ", uid=" + callingUid
790 + " requires " + r.permission);
791 return new ServiceLookupResult(null, r.permission);
792 }
793 return new ServiceLookupResult(r, null);
794 }
795 return null;
796 }
797
798 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
799 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
800 + why + " of " + r + " in app " + r.app);
801 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
802 + why + " of " + r.shortName);
803 long now = SystemClock.uptimeMillis();
804 if (r.executeNesting == 0 && r.app != null) {
805 if (r.app.executingServices.size() == 0) {
806 Message msg = mAm.mHandler.obtainMessage(
807 ActivityManagerService.SERVICE_TIMEOUT_MSG);
808 msg.obj = r.app;
809 mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
810 }
811 r.app.executingServices.add(r);
812 }
813 r.executeNesting++;
814 r.executingStart = now;
815 }
816
817 private final boolean requestServiceBindingLocked(ServiceRecord r,
818 IntentBindRecord i, boolean rebind) {
819 if (r.app == null || r.app.thread == null) {
820 // If service is not currently running, can't yet bind.
821 return false;
822 }
823 if ((!i.requested || rebind) && i.apps.size() > 0) {
824 try {
825 bumpServiceExecutingLocked(r, "bind");
826 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
827 if (!rebind) {
828 i.requested = true;
829 }
830 i.hasBound = true;
831 i.doRebind = false;
832 } catch (RemoteException e) {
833 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
834 return false;
835 }
836 }
837 return true;
838 }
839
840 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
841 boolean allowCancel) {
842 boolean canceled = false;
843
844 final long now = SystemClock.uptimeMillis();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700845
846 if ((r.serviceInfo.applicationInfo.flags
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700847 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
848 long minDuration = SERVICE_RESTART_DURATION;
849 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700850
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700851 // Any delivered but not yet finished starts should be put back
852 // on the pending list.
853 final int N = r.deliveredStarts.size();
854 if (N > 0) {
855 for (int i=N-1; i>=0; i--) {
856 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
857 si.removeUriPermissionsLocked();
858 if (si.intent == null) {
859 // We'll generate this again if needed.
860 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
861 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
862 r.pendingStarts.add(0, si);
863 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
864 dur *= 2;
865 if (minDuration < dur) minDuration = dur;
866 if (resetTime < dur) resetTime = dur;
867 } else {
868 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
869 + r.name);
870 canceled = true;
871 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700872 }
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700873 r.deliveredStarts.clear();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700874 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700875
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700876 r.totalRestartCount++;
877 if (r.restartDelay == 0) {
878 r.restartCount++;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700879 r.restartDelay = minDuration;
880 } else {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700881 // If it has been a "reasonably long time" since the service
882 // was started, then reset our restart duration back to
883 // the beginning, so we don't infinitely increase the duration
884 // on a service that just occasionally gets killed (which is
885 // a normal case, due to process being killed to reclaim memory).
886 if (now > (r.restartTime+resetTime)) {
887 r.restartCount = 1;
888 r.restartDelay = minDuration;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700889 } else {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700890 if ((r.serviceInfo.applicationInfo.flags
891 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
892 // Services in peristent processes will restart much more
893 // quickly, since they are pretty important. (Think SystemUI).
894 r.restartDelay += minDuration/2;
895 } else {
896 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
897 if (r.restartDelay < minDuration) {
898 r.restartDelay = minDuration;
899 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700900 }
901 }
902 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700903
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700904 r.nextRestartTime = now + r.restartDelay;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700905
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700906 // Make sure that we don't end up restarting a bunch of services
907 // all at the same time.
908 boolean repeat;
909 do {
910 repeat = false;
911 for (int i=mRestartingServices.size()-1; i>=0; i--) {
912 ServiceRecord r2 = mRestartingServices.get(i);
913 if (r2 != r && r.nextRestartTime
914 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
915 && r.nextRestartTime
916 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
917 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
918 r.restartDelay = r.nextRestartTime - now;
919 repeat = true;
920 break;
921 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700922 }
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700923 } while (repeat);
924
925 } else {
926 // Persistent processes are immediately restrted, so there is no
927 // reason to hold of on restarting their services.
928 r.totalRestartCount++;
929 r.restartCount = 0;
930 r.restartDelay = 0;
931 r.nextRestartTime = now;
932 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700933
934 if (!mRestartingServices.contains(r)) {
935 mRestartingServices.add(r);
936 }
937
938 r.cancelNotification();
939
940 mAm.mHandler.removeCallbacks(r.restarter);
941 mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
942 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
943 Slog.w(TAG, "Scheduling restart of crashed service "
944 + r.shortName + " in " + r.restartDelay + "ms");
945 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700946 r.userId, r.shortName, r.restartDelay);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700947
948 return canceled;
949 }
950
951 final void performServiceRestartLocked(ServiceRecord r) {
952 if (!mRestartingServices.contains(r)) {
953 return;
954 }
955 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
956 }
957
958 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
959 if (r.restartDelay == 0) {
960 return false;
961 }
962 r.resetRestartCounter();
963 mRestartingServices.remove(r);
964 mAm.mHandler.removeCallbacks(r.restarter);
965 return true;
966 }
967
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700968 private final String bringUpServiceLocked(ServiceRecord r,
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700969 int intentFlags, boolean whileRestarting) {
970 //Slog.i(TAG, "Bring up service:");
971 //r.dump(" ");
972
973 if (r.app != null && r.app.thread != null) {
974 sendServiceArgsLocked(r, false);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700975 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700976 }
977
978 if (!whileRestarting && r.restartDelay > 0) {
979 // If waiting for a restart, then do nothing.
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700980 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700981 }
982
983 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
984
985 // We are now bringing the service up, so no longer in the
986 // restarting state.
987 mRestartingServices.remove(r);
988
Dianne Hackborn80a4af22012-08-27 19:18:31 -0700989 // Make sure that the user who owns this service is started. If not,
990 // we don't want to allow it to run.
991 if (mAm.mStartedUsers.get(r.userId) == null) {
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700992 String msg = "Unable to launch app "
Dianne Hackborn80a4af22012-08-27 19:18:31 -0700993 + r.appInfo.packageName + "/"
994 + r.appInfo.uid + " for service "
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700995 + r.intent.getIntent() + ": user " + r.userId + " is stopped";
996 Slog.w(TAG, msg);
Dianne Hackborn80a4af22012-08-27 19:18:31 -0700997 bringDownServiceLocked(r, true);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700998 return msg;
Dianne Hackborn80a4af22012-08-27 19:18:31 -0700999 }
1000
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001001 // Service is now being launched, its package can't be stopped.
1002 try {
1003 AppGlobals.getPackageManager().setPackageStoppedState(
1004 r.packageName, false, r.userId);
1005 } catch (RemoteException e) {
1006 } catch (IllegalArgumentException e) {
1007 Slog.w(TAG, "Failed trying to unstop package "
1008 + r.packageName + ": " + e);
1009 }
1010
1011 final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
1012 final String procName = r.processName;
1013 ProcessRecord app;
1014
1015 if (!isolated) {
1016 app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
1017 if (DEBUG_MU)
1018 Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
1019 if (app != null && app.thread != null) {
1020 try {
1021 app.addPackage(r.appInfo.packageName);
1022 realStartServiceLocked(r, app);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001023 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001024 } catch (RemoteException e) {
1025 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
1026 }
1027
1028 // If a dead object exception was thrown -- fall through to
1029 // restart the application.
1030 }
1031 } else {
1032 // If this service runs in an isolated process, then each time
1033 // we call startProcessLocked() we will get a new isolated
1034 // process, starting another process if we are currently waiting
1035 // for a previous process to come up. To deal with this, we store
1036 // in the service any current isolated process it is running in or
1037 // waiting to have come up.
1038 app = r.isolatedProc;
1039 }
1040
1041 // Not running -- get it started, and enqueue this service record
1042 // to be executed when the app comes up.
1043 if (app == null) {
1044 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
1045 "service", r.name, false, isolated)) == null) {
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001046 String msg = "Unable to launch app "
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001047 + r.appInfo.packageName + "/"
1048 + r.appInfo.uid + " for service "
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001049 + r.intent.getIntent() + ": process is bad";
1050 Slog.w(TAG, msg);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001051 bringDownServiceLocked(r, true);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001052 return msg;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001053 }
1054 if (isolated) {
1055 r.isolatedProc = app;
1056 }
1057 }
1058
1059 if (!mPendingServices.contains(r)) {
1060 mPendingServices.add(r);
1061 }
1062
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001063 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001064 }
1065
1066 private final void requestServiceBindingsLocked(ServiceRecord r) {
1067 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
1068 while (bindings.hasNext()) {
1069 IntentBindRecord i = bindings.next();
1070 if (!requestServiceBindingLocked(r, i, false)) {
1071 break;
1072 }
1073 }
1074 }
1075
1076 private final void realStartServiceLocked(ServiceRecord r,
1077 ProcessRecord app) throws RemoteException {
1078 if (app.thread == null) {
1079 throw new RemoteException();
1080 }
1081 if (DEBUG_MU)
1082 Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
1083 + ", ProcessRecord.uid = " + app.uid);
1084 r.app = app;
1085 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
1086
1087 app.services.add(r);
1088 bumpServiceExecutingLocked(r, "create");
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001089 mAm.updateLruProcessLocked(app, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001090
1091 boolean created = false;
1092 try {
Jeff Sharkey9d6d8902012-11-09 17:32:43 -08001093 EventLogTags.writeAmCreateService(
1094 r.userId, System.identityHashCode(r), r.shortName, r.app.pid);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001095 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);
Jeff Sharkey9d6d8902012-11-09 17:32:43 -08001242 EventLogTags.writeAmDestroyService(
1243 r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001244
1245 mServiceMap.removeServiceByName(r.name, r.userId);
1246 mServiceMap.removeServiceByIntent(r.intent, r.userId);
1247 r.totalRestartCount = 0;
1248 unscheduleServiceRestartLocked(r);
1249
1250 // Also make sure it is not on the pending list.
1251 int N = mPendingServices.size();
1252 for (int i=0; i<N; i++) {
1253 if (mPendingServices.get(i) == r) {
1254 mPendingServices.remove(i);
1255 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
1256 i--;
1257 N--;
1258 }
1259 }
1260
1261 r.cancelNotification();
1262 r.isForeground = false;
1263 r.foregroundId = 0;
1264 r.foregroundNoti = null;
1265
1266 // Clear start entries.
1267 r.clearDeliveredStartsLocked();
1268 r.pendingStarts.clear();
1269
1270 if (r.app != null) {
1271 synchronized (r.stats.getBatteryStats()) {
1272 r.stats.stopLaunchedLocked();
1273 }
1274 r.app.services.remove(r);
1275 if (r.app.thread != null) {
1276 try {
1277 bumpServiceExecutingLocked(r, "stop");
1278 mStoppingServices.add(r);
1279 mAm.updateOomAdjLocked(r.app);
1280 r.app.thread.scheduleStopService(r);
1281 } catch (Exception e) {
1282 Slog.w(TAG, "Exception when stopping service "
1283 + r.shortName, e);
1284 serviceDoneExecutingLocked(r, true);
1285 }
1286 updateServiceForegroundLocked(r.app, false);
1287 } else {
1288 if (DEBUG_SERVICE) Slog.v(
1289 TAG, "Removed service that has no process: " + r);
1290 }
1291 } else {
1292 if (DEBUG_SERVICE) Slog.v(
1293 TAG, "Removed service that is not running: " + r);
1294 }
1295
1296 if (r.bindings.size() > 0) {
1297 r.bindings.clear();
1298 }
1299
1300 if (r.restarter instanceof ServiceRestarter) {
1301 ((ServiceRestarter)r.restarter).setService(null);
1302 }
1303 }
1304
1305 void removeConnectionLocked(
1306 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
1307 IBinder binder = c.conn.asBinder();
1308 AppBindRecord b = c.binding;
1309 ServiceRecord s = b.service;
1310 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
1311 if (clist != null) {
1312 clist.remove(c);
1313 if (clist.size() == 0) {
1314 s.connections.remove(binder);
1315 }
1316 }
1317 b.connections.remove(c);
1318 if (c.activity != null && c.activity != skipAct) {
1319 if (c.activity.connections != null) {
1320 c.activity.connections.remove(c);
1321 }
1322 }
1323 if (b.client != skipApp) {
1324 b.client.connections.remove(c);
1325 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
1326 b.client.updateHasAboveClientLocked();
1327 }
1328 }
1329 clist = mServiceConnections.get(binder);
1330 if (clist != null) {
1331 clist.remove(c);
1332 if (clist.size() == 0) {
1333 mServiceConnections.remove(binder);
1334 }
1335 }
1336
1337 if (b.connections.size() == 0) {
1338 b.intent.apps.remove(b.client);
1339 }
1340
1341 if (!c.serviceDead) {
1342 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
1343 + ": shouldUnbind=" + b.intent.hasBound);
1344 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
1345 && b.intent.hasBound) {
1346 try {
1347 bumpServiceExecutingLocked(s, "unbind");
1348 mAm.updateOomAdjLocked(s.app);
1349 b.intent.hasBound = false;
1350 // Assume the client doesn't want to know about a rebind;
1351 // we will deal with that later if it asks for one.
1352 b.intent.doRebind = false;
1353 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
1354 } catch (Exception e) {
1355 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
1356 serviceDoneExecutingLocked(s, true);
1357 }
1358 }
1359
1360 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
1361 bringDownServiceLocked(s, false);
1362 }
1363 }
1364 }
1365
1366 void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
1367 boolean inStopping = mStoppingServices.contains(r);
1368 if (r != null) {
1369 if (type == 1) {
1370 // This is a call from a service start... take care of
1371 // book-keeping.
1372 r.callStart = true;
1373 switch (res) {
1374 case Service.START_STICKY_COMPATIBILITY:
1375 case Service.START_STICKY: {
1376 // We are done with the associated start arguments.
1377 r.findDeliveredStart(startId, true);
1378 // Don't stop if killed.
1379 r.stopIfKilled = false;
1380 break;
1381 }
1382 case Service.START_NOT_STICKY: {
1383 // We are done with the associated start arguments.
1384 r.findDeliveredStart(startId, true);
1385 if (r.getLastStartId() == startId) {
1386 // There is no more work, and this service
1387 // doesn't want to hang around if killed.
1388 r.stopIfKilled = true;
1389 }
1390 break;
1391 }
1392 case Service.START_REDELIVER_INTENT: {
1393 // We'll keep this item until they explicitly
1394 // call stop for it, but keep track of the fact
1395 // that it was delivered.
1396 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
1397 if (si != null) {
1398 si.deliveryCount = 0;
1399 si.doneExecutingCount++;
1400 // Don't stop if killed.
1401 r.stopIfKilled = true;
1402 }
1403 break;
1404 }
1405 case Service.START_TASK_REMOVED_COMPLETE: {
1406 // Special processing for onTaskRemoved(). Don't
1407 // impact normal onStartCommand() processing.
1408 r.findDeliveredStart(startId, true);
1409 break;
1410 }
1411 default:
1412 throw new IllegalArgumentException(
1413 "Unknown service start result: " + res);
1414 }
1415 if (res == Service.START_STICKY_COMPATIBILITY) {
1416 r.callStart = false;
1417 }
1418 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001419 final long origId = Binder.clearCallingIdentity();
1420 serviceDoneExecutingLocked(r, inStopping);
1421 Binder.restoreCallingIdentity(origId);
1422 } else {
1423 Slog.w(TAG, "Done executing unknown service from pid "
1424 + Binder.getCallingPid());
1425 }
1426 }
1427
1428 private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
1429 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
1430 + ": nesting=" + r.executeNesting
1431 + ", inStopping=" + inStopping + ", app=" + r.app);
1432 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
1433 r.executeNesting--;
1434 if (r.executeNesting <= 0 && r.app != null) {
1435 if (DEBUG_SERVICE) Slog.v(TAG,
1436 "Nesting at 0 of " + r.shortName);
1437 r.app.executingServices.remove(r);
1438 if (r.app.executingServices.size() == 0) {
1439 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
1440 "No more executingServices of " + r.shortName);
1441 mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
1442 }
1443 if (inStopping) {
1444 if (DEBUG_SERVICE) Slog.v(TAG,
1445 "doneExecuting remove stopping " + r);
1446 mStoppingServices.remove(r);
1447 r.bindings.clear();
1448 }
1449 mAm.updateOomAdjLocked(r.app);
1450 }
1451 }
1452
1453 boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
1454 boolean didSomething = false;
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -07001455 // Collect any services that are waiting for this process to come up.
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001456 if (mPendingServices.size() > 0) {
1457 ServiceRecord sr = null;
1458 try {
1459 for (int i=0; i<mPendingServices.size(); i++) {
1460 sr = mPendingServices.get(i);
1461 if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
1462 || !processName.equals(sr.processName))) {
1463 continue;
1464 }
1465
1466 mPendingServices.remove(i);
1467 i--;
1468 realStartServiceLocked(sr, proc);
1469 didSomething = true;
1470 }
1471 } catch (Exception e) {
1472 Slog.w(TAG, "Exception in new application when starting service "
1473 + sr.shortName, e);
1474 throw e;
1475 }
1476 }
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -07001477 // Also, if there are any services that are waiting to restart and
1478 // would run in this process, now is a good time to start them. It would
1479 // be weird to bring up the process but arbitrarily not let the services
1480 // run at this point just because their restart time hasn't come up.
1481 if (mRestartingServices.size() > 0) {
1482 ServiceRecord sr = null;
1483 for (int i=0; i<mRestartingServices.size(); i++) {
1484 sr = mRestartingServices.get(i);
1485 if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
1486 || !processName.equals(sr.processName))) {
1487 continue;
1488 }
1489 mAm.mHandler.removeCallbacks(sr.restarter);
1490 mAm.mHandler.post(sr.restarter);
1491 }
1492 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001493 return didSomething;
1494 }
1495
1496 void processStartTimedOutLocked(ProcessRecord proc) {
1497 for (int i=0; i<mPendingServices.size(); i++) {
1498 ServiceRecord sr = mPendingServices.get(i);
1499 if ((proc.uid == sr.appInfo.uid
1500 && proc.processName.equals(sr.processName))
1501 || sr.isolatedProc == proc) {
1502 Slog.w(TAG, "Forcing bringing down service: " + sr);
1503 sr.isolatedProc = null;
1504 mPendingServices.remove(i);
1505 i--;
1506 bringDownServiceLocked(sr, true);
1507 }
1508 }
1509 }
1510
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001511 private boolean collectForceStopServicesLocked(String name, int userId,
1512 boolean evenPersistent, boolean doit,
1513 HashMap<ComponentName, ServiceRecord> services,
1514 ArrayList<ServiceRecord> result) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001515 boolean didSomething = false;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001516 for (ServiceRecord service : services.values()) {
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001517 if ((name == null || service.packageName.equals(name))
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001518 && (service.app == null || evenPersistent || !service.app.persistent)) {
1519 if (!doit) {
1520 return true;
1521 }
1522 didSomething = true;
1523 Slog.i(TAG, " Force stopping service " + service);
1524 if (service.app != null) {
1525 service.app.removed = true;
1526 }
1527 service.app = null;
1528 service.isolatedProc = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001529 result.add(service);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001530 }
1531 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001532 return didSomething;
1533 }
1534
1535 boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
1536 boolean didSomething = false;
1537 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
1538 if (userId == UserHandle.USER_ALL) {
1539 for (int i=0; i<mServiceMap.mServicesByNamePerUser.size(); i++) {
1540 didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
1541 doit, mServiceMap.mServicesByNamePerUser.valueAt(i), services);
1542 if (!doit && didSomething) {
1543 return true;
1544 }
1545 }
1546 } else {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001547 HashMap<ComponentName, ServiceRecord> items
1548 = mServiceMap.mServicesByNamePerUser.get(userId);
1549 if (items != null) {
1550 didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
1551 doit, items, services);
1552 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001553 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001554
1555 int N = services.size();
1556 for (int i=0; i<N; i++) {
1557 bringDownServiceLocked(services.get(i), true);
1558 }
1559 return didSomething;
1560 }
1561
1562 void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
1563 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
1564 for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
1565 if (sr.packageName.equals(component.getPackageName())) {
1566 services.add(sr);
1567 }
1568 }
1569
1570 // Take care of any running services associated with the app.
1571 for (int i=0; i<services.size(); i++) {
1572 ServiceRecord sr = services.get(i);
1573 if (sr.startRequested) {
1574 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
1575 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
1576 stopServiceLocked(sr);
1577 } else {
1578 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
1579 sr.makeNextStartId(), baseIntent, null));
1580 if (sr.app != null && sr.app.thread != null) {
1581 sendServiceArgsLocked(sr, false);
1582 }
1583 }
1584 }
1585 }
1586 }
1587
1588 final void killServicesLocked(ProcessRecord app,
1589 boolean allowRestart) {
1590 // Report disconnected services.
1591 if (false) {
1592 // XXX we are letting the client link to the service for
1593 // death notifications.
1594 if (app.services.size() > 0) {
1595 Iterator<ServiceRecord> it = app.services.iterator();
1596 while (it.hasNext()) {
1597 ServiceRecord r = it.next();
1598 if (r.connections.size() > 0) {
1599 Iterator<ArrayList<ConnectionRecord>> jt
1600 = r.connections.values().iterator();
1601 while (jt.hasNext()) {
1602 ArrayList<ConnectionRecord> cl = jt.next();
1603 for (int i=0; i<cl.size(); i++) {
1604 ConnectionRecord c = cl.get(i);
1605 if (c.binding.client != app) {
1606 try {
1607 //c.conn.connected(r.className, null);
1608 } catch (Exception e) {
1609 // todo: this should be asynchronous!
1610 Slog.w(TAG, "Exception thrown disconnected servce "
1611 + r.shortName
1612 + " from app " + app.processName, e);
1613 }
1614 }
1615 }
1616 }
1617 }
1618 }
1619 }
1620 }
1621
1622 // Clean up any connections this application has to other services.
1623 if (app.connections.size() > 0) {
1624 Iterator<ConnectionRecord> it = app.connections.iterator();
1625 while (it.hasNext()) {
1626 ConnectionRecord r = it.next();
1627 removeConnectionLocked(r, app, null);
1628 }
1629 }
1630 app.connections.clear();
1631
1632 if (app.services.size() != 0) {
1633 // Any services running in the application need to be placed
1634 // back in the pending list.
1635 Iterator<ServiceRecord> it = app.services.iterator();
1636 while (it.hasNext()) {
1637 ServiceRecord sr = it.next();
1638 synchronized (sr.stats.getBatteryStats()) {
1639 sr.stats.stopLaunchedLocked();
1640 }
1641 sr.app = null;
1642 sr.isolatedProc = null;
1643 sr.executeNesting = 0;
1644 if (mStoppingServices.remove(sr)) {
1645 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
1646 }
1647
1648 boolean hasClients = sr.bindings.size() > 0;
1649 if (hasClients) {
1650 Iterator<IntentBindRecord> bindings
1651 = sr.bindings.values().iterator();
1652 while (bindings.hasNext()) {
1653 IntentBindRecord b = bindings.next();
1654 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
1655 + ": shouldUnbind=" + b.hasBound);
1656 b.binder = null;
1657 b.requested = b.received = b.hasBound = false;
1658 }
1659 }
1660
1661 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
1662 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
1663 Slog.w(TAG, "Service crashed " + sr.crashCount
1664 + " times, stopping: " + sr);
1665 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001666 sr.userId, sr.crashCount, sr.shortName, app.pid);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001667 bringDownServiceLocked(sr, true);
1668 } else if (!allowRestart) {
1669 bringDownServiceLocked(sr, true);
1670 } else {
1671 boolean canceled = scheduleServiceRestartLocked(sr, true);
1672
1673 // Should the service remain running? Note that in the
1674 // extreme case of so many attempts to deliver a command
1675 // that it failed we also will stop it here.
1676 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
1677 if (sr.pendingStarts.size() == 0) {
1678 sr.startRequested = false;
1679 if (!hasClients) {
1680 // Whoops, no reason to restart!
1681 bringDownServiceLocked(sr, true);
1682 }
1683 }
1684 }
1685 }
1686 }
1687
1688 if (!allowRestart) {
1689 app.services.clear();
1690 }
1691 }
1692
1693 // Make sure we have no more records on the stopping list.
1694 int i = mStoppingServices.size();
1695 while (i > 0) {
1696 i--;
1697 ServiceRecord sr = mStoppingServices.get(i);
1698 if (sr.app == app) {
1699 mStoppingServices.remove(i);
1700 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
1701 }
1702 }
1703
1704 app.executingServices.clear();
1705 }
1706
1707 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
1708 ActivityManager.RunningServiceInfo info =
1709 new ActivityManager.RunningServiceInfo();
1710 info.service = r.name;
1711 if (r.app != null) {
1712 info.pid = r.app.pid;
1713 }
1714 info.uid = r.appInfo.uid;
1715 info.process = r.processName;
1716 info.foreground = r.isForeground;
1717 info.activeSince = r.createTime;
1718 info.started = r.startRequested;
1719 info.clientCount = r.connections.size();
1720 info.crashCount = r.crashCount;
1721 info.lastActivityTime = r.lastActivity;
1722 if (r.isForeground) {
1723 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
1724 }
1725 if (r.startRequested) {
1726 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
1727 }
1728 if (r.app != null && r.app.pid == ActivityManagerService.MY_PID) {
1729 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
1730 }
1731 if (r.app != null && r.app.persistent) {
1732 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
1733 }
1734
1735 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
1736 for (int i=0; i<connl.size(); i++) {
1737 ConnectionRecord conn = connl.get(i);
1738 if (conn.clientLabel != 0) {
1739 info.clientPackage = conn.binding.client.info.packageName;
1740 info.clientLabel = conn.clientLabel;
1741 return info;
1742 }
1743 }
1744 }
1745 return info;
1746 }
1747
1748 List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum,
1749 int flags) {
1750 ArrayList<ActivityManager.RunningServiceInfo> res
1751 = new ArrayList<ActivityManager.RunningServiceInfo>();
1752
Dianne Hackborn0c380492012-08-20 17:23:30 -07001753 final int uid = Binder.getCallingUid();
1754 final long ident = Binder.clearCallingIdentity();
1755 try {
1756 if (ActivityManager.checkUidPermission(
1757 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1758 uid) == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn1676c852012-09-10 14:52:30 -07001759 int[] users = mAm.getUsersLocked();
1760 for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
1761 if (mServiceMap.getAllServices(users[ui]).size() > 0) {
Dianne Hackborn0c380492012-08-20 17:23:30 -07001762 Iterator<ServiceRecord> it = mServiceMap.getAllServices(
Dianne Hackborn1676c852012-09-10 14:52:30 -07001763 users[ui]).iterator();
Dianne Hackborn0c380492012-08-20 17:23:30 -07001764 while (it.hasNext() && res.size() < maxNum) {
1765 res.add(makeRunningServiceInfoLocked(it.next()));
1766 }
1767 }
1768 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001769
Dianne Hackborn0c380492012-08-20 17:23:30 -07001770 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
1771 ServiceRecord r = mRestartingServices.get(i);
1772 ActivityManager.RunningServiceInfo info =
1773 makeRunningServiceInfoLocked(r);
1774 info.restarting = r.nextRestartTime;
1775 res.add(info);
1776 }
1777 } else {
1778 int userId = UserHandle.getUserId(uid);
1779 if (mServiceMap.getAllServices(userId).size() > 0) {
1780 Iterator<ServiceRecord> it
1781 = mServiceMap.getAllServices(userId).iterator();
1782 while (it.hasNext() && res.size() < maxNum) {
1783 res.add(makeRunningServiceInfoLocked(it.next()));
1784 }
1785 }
1786
1787 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
1788 ServiceRecord r = mRestartingServices.get(i);
1789 if (r.userId == userId) {
1790 ActivityManager.RunningServiceInfo info =
1791 makeRunningServiceInfoLocked(r);
1792 info.restarting = r.nextRestartTime;
1793 res.add(info);
1794 }
1795 }
1796 }
1797 } finally {
1798 Binder.restoreCallingIdentity(ident);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001799 }
1800
1801 return res;
1802 }
1803
1804 public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001805 int userId = UserHandle.getUserId(Binder.getCallingUid());
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001806 ServiceRecord r = mServiceMap.getServiceByName(name, userId);
1807 if (r != null) {
1808 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
1809 for (int i=0; i<conn.size(); i++) {
1810 if (conn.get(i).clientIntent != null) {
1811 return conn.get(i).clientIntent;
1812 }
1813 }
1814 }
1815 }
1816 return null;
1817 }
1818
1819 void serviceTimeout(ProcessRecord proc) {
1820 String anrMessage = null;
1821
1822 synchronized(this) {
1823 if (proc.executingServices.size() == 0 || proc.thread == null) {
1824 return;
1825 }
1826 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
1827 Iterator<ServiceRecord> it = proc.executingServices.iterator();
1828 ServiceRecord timeout = null;
1829 long nextTime = 0;
1830 while (it.hasNext()) {
1831 ServiceRecord sr = it.next();
1832 if (sr.executingStart < maxTime) {
1833 timeout = sr;
1834 break;
1835 }
1836 if (sr.executingStart > nextTime) {
1837 nextTime = sr.executingStart;
1838 }
1839 }
1840 if (timeout != null && mAm.mLruProcesses.contains(proc)) {
1841 Slog.w(TAG, "Timeout executing service: " + timeout);
1842 anrMessage = "Executing service " + timeout.shortName;
1843 } else {
1844 Message msg = mAm.mHandler.obtainMessage(
1845 ActivityManagerService.SERVICE_TIMEOUT_MSG);
1846 msg.obj = proc;
1847 mAm.mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
1848 }
1849 }
1850
1851 if (anrMessage != null) {
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -07001852 mAm.appNotResponding(proc, null, null, false, anrMessage);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001853 }
1854 }
1855
1856 /**
1857 * Prints a list of ServiceRecords (dumpsys activity services)
1858 */
1859 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
1860 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
1861 boolean needSep = false;
1862
1863 ItemMatcher matcher = new ItemMatcher();
1864 matcher.build(args, opti);
1865
1866 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
1867 try {
Dianne Hackborn1676c852012-09-10 14:52:30 -07001868 int[] users = mAm.getUsersLocked();
1869 for (int user : users) {
1870 if (mServiceMap.getAllServices(user).size() > 0) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001871 boolean printed = false;
1872 long nowReal = SystemClock.elapsedRealtime();
1873 Iterator<ServiceRecord> it = mServiceMap.getAllServices(
Dianne Hackborn1676c852012-09-10 14:52:30 -07001874 user).iterator();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001875 needSep = false;
1876 while (it.hasNext()) {
1877 ServiceRecord r = it.next();
1878 if (!matcher.match(r, r.name)) {
1879 continue;
1880 }
1881 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1882 continue;
1883 }
1884 if (!printed) {
Dianne Hackborn1676c852012-09-10 14:52:30 -07001885 if (user != 0) {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -07001886 pw.println();
1887 }
Dianne Hackborn1676c852012-09-10 14:52:30 -07001888 pw.println(" User " + user + " active services:");
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001889 printed = true;
1890 }
1891 if (needSep) {
1892 pw.println();
1893 }
1894 pw.print(" * ");
1895 pw.println(r);
1896 if (dumpAll) {
1897 r.dump(pw, " ");
1898 needSep = true;
1899 } else {
1900 pw.print(" app=");
1901 pw.println(r.app);
1902 pw.print(" created=");
1903 TimeUtils.formatDuration(r.createTime, nowReal, pw);
1904 pw.print(" started=");
1905 pw.print(r.startRequested);
1906 pw.print(" connections=");
1907 pw.println(r.connections.size());
1908 if (r.connections.size() > 0) {
1909 pw.println(" Connections:");
1910 for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
1911 for (int i = 0; i < clist.size(); i++) {
1912 ConnectionRecord conn = clist.get(i);
1913 pw.print(" ");
1914 pw.print(conn.binding.intent.intent.getIntent()
1915 .toShortString(false, false, false, false));
1916 pw.print(" -> ");
1917 ProcessRecord proc = conn.binding.client;
1918 pw.println(proc != null ? proc.toShortString() : "null");
1919 }
1920 }
1921 }
1922 }
1923 if (dumpClient && r.app != null && r.app.thread != null) {
1924 pw.println(" Client:");
1925 pw.flush();
1926 try {
1927 TransferPipe tp = new TransferPipe();
1928 try {
1929 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
1930 r, args);
1931 tp.setBufferPrefix(" ");
1932 // Short timeout, since blocking here can
1933 // deadlock with the application.
1934 tp.go(fd, 2000);
1935 } finally {
1936 tp.kill();
1937 }
1938 } catch (IOException e) {
1939 pw.println(" Failure while dumping the service: " + e);
1940 } catch (RemoteException e) {
1941 pw.println(" Got a RemoteException while dumping the service");
1942 }
1943 needSep = true;
1944 }
1945 }
1946 needSep = printed;
1947 }
1948 }
Amith Yamasani258848d2012-08-10 17:06:33 -07001949 } catch (Exception e) {
1950 Log.w(TAG, "Exception in dumpServicesLocked: " + e);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001951 }
1952
1953 if (mPendingServices.size() > 0) {
1954 boolean printed = false;
1955 for (int i=0; i<mPendingServices.size(); i++) {
1956 ServiceRecord r = mPendingServices.get(i);
1957 if (!matcher.match(r, r.name)) {
1958 continue;
1959 }
1960 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1961 continue;
1962 }
1963 if (!printed) {
1964 if (needSep) pw.println(" ");
1965 needSep = true;
1966 pw.println(" Pending services:");
1967 printed = true;
1968 }
1969 pw.print(" * Pending "); pw.println(r);
1970 r.dump(pw, " ");
1971 }
1972 needSep = true;
1973 }
1974
1975 if (mRestartingServices.size() > 0) {
1976 boolean printed = false;
1977 for (int i=0; i<mRestartingServices.size(); i++) {
1978 ServiceRecord r = mRestartingServices.get(i);
1979 if (!matcher.match(r, r.name)) {
1980 continue;
1981 }
1982 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1983 continue;
1984 }
1985 if (!printed) {
1986 if (needSep) pw.println(" ");
1987 needSep = true;
1988 pw.println(" Restarting services:");
1989 printed = true;
1990 }
1991 pw.print(" * Restarting "); pw.println(r);
1992 r.dump(pw, " ");
1993 }
1994 needSep = true;
1995 }
1996
1997 if (mStoppingServices.size() > 0) {
1998 boolean printed = false;
1999 for (int i=0; i<mStoppingServices.size(); i++) {
2000 ServiceRecord r = mStoppingServices.get(i);
2001 if (!matcher.match(r, r.name)) {
2002 continue;
2003 }
2004 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
2005 continue;
2006 }
2007 if (!printed) {
2008 if (needSep) pw.println(" ");
2009 needSep = true;
2010 pw.println(" Stopping services:");
2011 printed = true;
2012 }
2013 pw.print(" * Stopping "); pw.println(r);
2014 r.dump(pw, " ");
2015 }
2016 needSep = true;
2017 }
2018
2019 if (dumpAll) {
2020 if (mServiceConnections.size() > 0) {
2021 boolean printed = false;
2022 Iterator<ArrayList<ConnectionRecord>> it
2023 = mServiceConnections.values().iterator();
2024 while (it.hasNext()) {
2025 ArrayList<ConnectionRecord> r = it.next();
2026 for (int i=0; i<r.size(); i++) {
2027 ConnectionRecord cr = r.get(i);
2028 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
2029 continue;
2030 }
2031 if (dumpPackage != null && (cr.binding.client == null
2032 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
2033 continue;
2034 }
2035 if (!printed) {
2036 if (needSep) pw.println(" ");
2037 needSep = true;
2038 pw.println(" Connection bindings to services:");
2039 printed = true;
2040 }
2041 pw.print(" * "); pw.println(cr);
2042 cr.dump(pw, " ");
2043 }
2044 }
2045 needSep = true;
2046 }
2047 }
2048
2049 return needSep;
2050 }
2051
2052 /**
2053 * There are three ways to call this:
2054 * - no service specified: dump all the services
2055 * - a flattened component name that matched an existing service was specified as the
2056 * first arg: dump that one service
2057 * - the first arg isn't the flattened component name of an existing service:
2058 * dump all services whose component contains the first arg as a substring
2059 */
2060 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
2061 int opti, boolean dumpAll) {
2062 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
2063
Dianne Hackborn1676c852012-09-10 14:52:30 -07002064 synchronized (this) {
2065 int[] users = mAm.getUsersLocked();
2066 if ("all".equals(name)) {
2067 for (int user : users) {
2068 for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
Amith Yamasani258848d2012-08-10 17:06:33 -07002069 services.add(r1);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002070 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002071 }
Dianne Hackborn1676c852012-09-10 14:52:30 -07002072 } else {
2073 ComponentName componentName = name != null
2074 ? ComponentName.unflattenFromString(name) : null;
2075 int objectId = 0;
2076 if (componentName == null) {
2077 // Not a '/' separated full component name; maybe an object ID?
2078 try {
2079 objectId = Integer.parseInt(name, 16);
2080 name = null;
2081 componentName = null;
2082 } catch (RuntimeException e) {
2083 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002084 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002085
Dianne Hackborn1676c852012-09-10 14:52:30 -07002086 for (int user : users) {
2087 for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
Amith Yamasani258848d2012-08-10 17:06:33 -07002088 if (componentName != null) {
2089 if (r1.name.equals(componentName)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002090 services.add(r1);
2091 }
Amith Yamasani258848d2012-08-10 17:06:33 -07002092 } else if (name != null) {
2093 if (r1.name.flattenToString().contains(name)) {
2094 services.add(r1);
2095 }
2096 } else if (System.identityHashCode(r1) == objectId) {
2097 services.add(r1);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002098 }
2099 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002100 }
2101 }
2102 }
2103
2104 if (services.size() <= 0) {
2105 return false;
2106 }
2107
2108 boolean needSep = false;
2109 for (int i=0; i<services.size(); i++) {
2110 if (needSep) {
2111 pw.println();
2112 }
2113 needSep = true;
2114 dumpService("", fd, pw, services.get(i), args, dumpAll);
2115 }
2116 return true;
2117 }
2118
2119 /**
2120 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
2121 * there is a thread associated with the service.
2122 */
2123 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
2124 final ServiceRecord r, String[] args, boolean dumpAll) {
2125 String innerPrefix = prefix + " ";
2126 synchronized (this) {
2127 pw.print(prefix); pw.print("SERVICE ");
2128 pw.print(r.shortName); pw.print(" ");
2129 pw.print(Integer.toHexString(System.identityHashCode(r)));
2130 pw.print(" pid=");
2131 if (r.app != null) pw.println(r.app.pid);
2132 else pw.println("(not running)");
2133 if (dumpAll) {
2134 r.dump(pw, innerPrefix);
2135 }
2136 }
2137 if (r.app != null && r.app.thread != null) {
2138 pw.print(prefix); pw.println(" Client:");
2139 pw.flush();
2140 try {
2141 TransferPipe tp = new TransferPipe();
2142 try {
2143 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
2144 tp.setBufferPrefix(prefix + " ");
2145 tp.go(fd);
2146 } finally {
2147 tp.kill();
2148 }
2149 } catch (IOException e) {
2150 pw.println(prefix + " Failure while dumping the service: " + e);
2151 } catch (RemoteException e) {
2152 pw.println(prefix + " Got a RemoteException while dumping the service");
2153 }
2154 }
2155 }
2156
2157}