blob: 795e1424844c9f5f1121f68a6c03c7a5f2dc3d1c [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;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070030import com.android.internal.os.TransferPipe;
Dianne Hackborn599db5c2012-08-03 19:28:48 -070031import com.android.server.am.ActivityManagerService.ItemMatcher;
32import com.android.server.am.ActivityManagerService.NeededUriGrants;
33
34import android.app.ActivityManager;
35import android.app.AppGlobals;
36import android.app.IApplicationThread;
37import android.app.IServiceConnection;
38import android.app.Notification;
39import android.app.PendingIntent;
40import android.app.Service;
41import android.content.ComponentName;
42import android.content.Context;
43import android.content.Intent;
44import android.content.pm.ApplicationInfo;
45import android.content.pm.PackageManager;
46import android.content.pm.ResolveInfo;
47import android.content.pm.ServiceInfo;
Dianne Hackborn599db5c2012-08-03 19:28:48 -070048import android.os.Binder;
49import android.os.IBinder;
50import android.os.Message;
51import android.os.Process;
52import android.os.RemoteException;
53import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070054import android.os.UserHandle;
Dianne Hackborn599db5c2012-08-03 19:28:48 -070055import android.util.EventLog;
56import android.util.Log;
57import android.util.Slog;
58import android.util.SparseArray;
59import android.util.TimeUtils;
60
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070061public final class ActiveServices {
Dianne Hackborn599db5c2012-08-03 19:28:48 -070062 static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
63 static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
64 static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
65 static final String TAG = ActivityManagerService.TAG;
66 static final String TAG_MU = ActivityManagerService.TAG_MU;
67
68 // How long we wait for a service to finish executing.
69 static final int SERVICE_TIMEOUT = 20*1000;
70
71 // How long a service needs to be running until restarting its process
72 // is no longer considered to be a relaunch of the service.
73 static final int SERVICE_RESTART_DURATION = 5*1000;
74
75 // How long a service needs to be running until it will start back at
76 // SERVICE_RESTART_DURATION after being killed.
77 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
78
79 // Multiplying factor to increase restart duration time by, for each time
80 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
81 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
82
83 // The minimum amount of time between restarting services that we allow.
84 // That is, when multiple services are restarting, we won't allow each
85 // to restart less than this amount of time from the last one.
86 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
87
88 // Maximum amount of time for there to be no activity on a service before
89 // we consider it non-essential and allow its process to go on the
90 // LRU background list.
91 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
92
93 final ActivityManagerService mAm;
94
95 final ServiceMap mServiceMap = new ServiceMap();
96
97 /**
98 * All currently bound service connections. Keys are the IBinder of
99 * the client's IServiceConnection.
100 */
101 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
102 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
103
104 /**
105 * List of services that we have been asked to start,
106 * but haven't yet been able to. It is used to hold start requests
107 * while waiting for their corresponding application thread to get
108 * going.
109 */
110 final ArrayList<ServiceRecord> mPendingServices
111 = new ArrayList<ServiceRecord>();
112
113 /**
114 * List of services that are scheduled to restart following a crash.
115 */
116 final ArrayList<ServiceRecord> mRestartingServices
117 = new ArrayList<ServiceRecord>();
118
119 /**
120 * List of services that are in the process of being stopped.
121 */
122 final ArrayList<ServiceRecord> mStoppingServices
123 = new ArrayList<ServiceRecord>();
124
125 static class ServiceMap {
126
127 private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
128 = new SparseArray<HashMap<ComponentName, ServiceRecord>>();
129 private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
130 mServicesByIntentPerUser = new SparseArray<
131 HashMap<Intent.FilterComparison, ServiceRecord>>();
132
133 ServiceRecord getServiceByName(ComponentName name, int callingUser) {
134 // TODO: Deal with global services
135 if (DEBUG_MU)
136 Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
137 return getServices(callingUser).get(name);
138 }
139
140 ServiceRecord getServiceByName(ComponentName name) {
141 return getServiceByName(name, -1);
142 }
143
144 ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
145 // TODO: Deal with global services
146 if (DEBUG_MU)
147 Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
148 return getServicesByIntent(callingUser).get(filter);
149 }
150
151 ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
152 return getServiceByIntent(filter, -1);
153 }
154
155 void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
156 // TODO: Deal with global services
157 getServices(callingUser).put(name, value);
158 }
159
160 void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
161 ServiceRecord value) {
162 // TODO: Deal with global services
163 getServicesByIntent(callingUser).put(filter, value);
164 }
165
166 void removeServiceByName(ComponentName name, int callingUser) {
167 // TODO: Deal with global services
168 ServiceRecord removed = getServices(callingUser).remove(name);
169 if (DEBUG_MU)
170 Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
171 + " removed=" + removed);
172 }
173
174 void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
175 // TODO: Deal with global services
176 ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
177 if (DEBUG_MU)
178 Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
179 + " removed=" + removed);
180 }
181
182 Collection<ServiceRecord> getAllServices(int callingUser) {
183 // TODO: Deal with global services
184 return getServices(callingUser).values();
185 }
186
187 private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700188 HashMap<ComponentName, ServiceRecord> map = mServicesByNamePerUser.get(callingUser);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700189 if (map == null) {
190 map = new HashMap<ComponentName, ServiceRecord>();
191 mServicesByNamePerUser.put(callingUser, map);
192 }
193 return map;
194 }
195
196 private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
197 int callingUser) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700198 HashMap<Intent.FilterComparison, ServiceRecord> map
199 = mServicesByIntentPerUser.get(callingUser);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700200 if (map == null) {
201 map = new HashMap<Intent.FilterComparison, ServiceRecord>();
202 mServicesByIntentPerUser.put(callingUser, map);
203 }
204 return map;
205 }
206 }
207
208 public ActiveServices(ActivityManagerService service) {
209 mAm = service;
210 }
211
212 ComponentName startServiceLocked(IApplicationThread caller,
213 Intent service, String resolvedType,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700214 int callingPid, int callingUid, int userId) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700215 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
216 + " type=" + resolvedType + " args=" + service.getExtras());
217
218 if (caller != null) {
219 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
220 if (callerApp == null) {
221 throw new SecurityException(
222 "Unable to find app for caller " + caller
223 + " (pid=" + Binder.getCallingPid()
224 + ") when starting service " + service);
225 }
226 }
227
228 ServiceLookupResult res =
229 retrieveServiceLocked(service, resolvedType,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700230 callingPid, callingUid, userId, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700231 if (res == null) {
232 return null;
233 }
234 if (res.record == null) {
235 return new ComponentName("!", res.permission != null
236 ? res.permission : "private to package");
237 }
238 ServiceRecord r = res.record;
239 NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
240 callingUid, r.packageName, service, service.getFlags(), null);
241 if (unscheduleServiceRestartLocked(r)) {
242 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
243 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700244 r.lastActivity = SystemClock.uptimeMillis();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700245 r.startRequested = true;
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700246 if (r.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700247 r.tracker.setStarted(true, mAm.mProcessTracker.getMemFactorLocked(), r.lastActivity);
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700248 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700249 r.callStart = false;
250 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
251 service, neededGrants));
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700252 synchronized (r.stats.getBatteryStats()) {
253 r.stats.startRunningLocked();
254 }
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700255 String error = bringUpServiceLocked(r, service.getFlags(), false);
256 if (error != null) {
257 return new ComponentName("!!", error);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700258 }
259 return r.name;
260 }
261
262 private void stopServiceLocked(ServiceRecord service) {
263 synchronized (service.stats.getBatteryStats()) {
264 service.stats.stopRunningLocked();
265 }
266 service.startRequested = false;
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700267 if (service.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700268 service.tracker.setStarted(false, mAm.mProcessTracker.getMemFactorLocked(),
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700269 SystemClock.uptimeMillis());
270 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700271 service.callStart = false;
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700272 bringDownServiceIfNeededLocked(service, false, false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700273 }
274
275 int stopServiceLocked(IApplicationThread caller, Intent service,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700276 String resolvedType, int userId) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700277 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
278 + " type=" + resolvedType);
279
280 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
281 if (caller != null && callerApp == null) {
282 throw new SecurityException(
283 "Unable to find app for caller " + caller
284 + " (pid=" + Binder.getCallingPid()
285 + ") when stopping service " + service);
286 }
287
288 // If this service is active, make sure it is stopped.
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700289 ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700290 Binder.getCallingPid(), Binder.getCallingUid(), userId, false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700291 if (r != null) {
292 if (r.record != null) {
293 final long origId = Binder.clearCallingIdentity();
294 try {
295 stopServiceLocked(r.record);
296 } finally {
297 Binder.restoreCallingIdentity(origId);
298 }
299 return 1;
300 }
301 return -1;
302 }
303
304 return 0;
305 }
306
307 IBinder peekServiceLocked(Intent service, String resolvedType) {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700308 ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
309 Binder.getCallingPid(), Binder.getCallingUid(),
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700310 UserHandle.getCallingUserId(), false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700311
312 IBinder ret = null;
313 if (r != null) {
314 // r.record is null if findServiceLocked() failed the caller permission check
315 if (r.record == null) {
316 throw new SecurityException(
317 "Permission Denial: Accessing service " + r.record.name
318 + " from pid=" + Binder.getCallingPid()
319 + ", uid=" + Binder.getCallingUid()
320 + " requires " + r.permission);
321 }
322 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
323 if (ib != null) {
324 ret = ib.binder;
325 }
326 }
327
328 return ret;
329 }
330
331 boolean stopServiceTokenLocked(ComponentName className, IBinder token,
332 int startId) {
333 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
334 + " " + token + " startId=" + startId);
Dianne Hackborn41203752012-08-31 14:05:51 -0700335 ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700336 if (r != null) {
337 if (startId >= 0) {
338 // Asked to only stop if done with all work. Note that
339 // to avoid leaks, we will take this as dropping all
340 // start items up to and including this one.
341 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
342 if (si != null) {
343 while (r.deliveredStarts.size() > 0) {
344 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
345 cur.removeUriPermissionsLocked();
346 if (cur == si) {
347 break;
348 }
349 }
350 }
351
352 if (r.getLastStartId() != startId) {
353 return false;
354 }
355
356 if (r.deliveredStarts.size() > 0) {
357 Slog.w(TAG, "stopServiceToken startId " + startId
358 + " is last, but have " + r.deliveredStarts.size()
359 + " remaining args");
360 }
361 }
362
363 synchronized (r.stats.getBatteryStats()) {
364 r.stats.stopRunningLocked();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700365 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700366 r.startRequested = false;
367 if (r.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700368 r.tracker.setStarted(false, mAm.mProcessTracker.getMemFactorLocked(),
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700369 SystemClock.uptimeMillis());
370 }
371 r.callStart = false;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700372 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700373 bringDownServiceIfNeededLocked(r, false, false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700374 Binder.restoreCallingIdentity(origId);
375 return true;
376 }
377 return false;
378 }
379
380 public void setServiceForegroundLocked(ComponentName className, IBinder token,
381 int id, Notification notification, boolean removeNotification) {
Dianne Hackborn41203752012-08-31 14:05:51 -0700382 final int userId = UserHandle.getCallingUserId();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700383 final long origId = Binder.clearCallingIdentity();
384 try {
Dianne Hackborn41203752012-08-31 14:05:51 -0700385 ServiceRecord r = findServiceLocked(className, token, userId);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700386 if (r != null) {
387 if (id != 0) {
388 if (notification == null) {
389 throw new IllegalArgumentException("null notification");
390 }
391 if (r.foregroundId != id) {
392 r.cancelNotification();
393 r.foregroundId = id;
394 }
395 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
396 r.foregroundNoti = notification;
397 r.isForeground = true;
398 r.postNotification();
399 if (r.app != null) {
400 updateServiceForegroundLocked(r.app, true);
401 }
402 } else {
403 if (r.isForeground) {
404 r.isForeground = false;
405 if (r.app != null) {
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700406 mAm.updateLruProcessLocked(r.app, false);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700407 updateServiceForegroundLocked(r.app, true);
408 }
409 }
410 if (removeNotification) {
411 r.cancelNotification();
412 r.foregroundId = 0;
413 r.foregroundNoti = null;
414 }
415 }
416 }
417 } finally {
418 Binder.restoreCallingIdentity(origId);
419 }
420 }
421
422 private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
423 boolean anyForeground = false;
Dianne Hackbornc8230512013-07-13 21:32:12 -0700424 for (int i=proc.services.size()-1; i>=0; i--) {
425 ServiceRecord sr = proc.services.valueAt(i);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700426 if (sr.isForeground) {
427 anyForeground = true;
428 break;
429 }
430 }
431 if (anyForeground != proc.foregroundServices) {
432 proc.foregroundServices = anyForeground;
433 if (oomAdj) {
434 mAm.updateOomAdjLocked();
435 }
436 }
437 }
438
439 int bindServiceLocked(IApplicationThread caller, IBinder token,
440 Intent service, String resolvedType,
441 IServiceConnection connection, int flags, int userId) {
442 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
443 + " type=" + resolvedType + " conn=" + connection.asBinder()
444 + " flags=0x" + Integer.toHexString(flags));
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700445 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
446 if (callerApp == null) {
447 throw new SecurityException(
448 "Unable to find app for caller " + caller
449 + " (pid=" + Binder.getCallingPid()
450 + ") when binding service " + service);
451 }
452
453 ActivityRecord activity = null;
454 if (token != null) {
Craig Mautnerd2328952013-03-05 12:46:26 -0800455 activity = ActivityRecord.isInStackLocked(token);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700456 if (activity == null) {
457 Slog.w(TAG, "Binding with unknown activity: " + token);
458 return 0;
459 }
460 }
461
462 int clientLabel = 0;
463 PendingIntent clientIntent = null;
464
465 if (callerApp.info.uid == Process.SYSTEM_UID) {
466 // Hacky kind of thing -- allow system stuff to tell us
467 // what they are, so we can report this elsewhere for
468 // others to know why certain services are running.
469 try {
470 clientIntent = (PendingIntent)service.getParcelableExtra(
471 Intent.EXTRA_CLIENT_INTENT);
472 } catch (RuntimeException e) {
473 }
474 if (clientIntent != null) {
475 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
476 if (clientLabel != 0) {
477 // There are no useful extras in the intent, trash them.
478 // System code calling with this stuff just needs to know
479 // this will happen.
480 service = service.cloneFilter();
481 }
482 }
483 }
484
485 ServiceLookupResult res =
486 retrieveServiceLocked(service, resolvedType,
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700487 Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700488 if (res == null) {
489 return 0;
490 }
491 if (res.record == null) {
492 return -1;
493 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700494 ServiceRecord s = res.record;
495
496 final long origId = Binder.clearCallingIdentity();
497
498 try {
499 if (unscheduleServiceRestartLocked(s)) {
500 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
501 + s);
502 }
503
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700504 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
505 s.lastActivity = SystemClock.uptimeMillis();
506 if (!s.hasAutoCreateConnections()) {
507 // This is the first binding, let the tracker know.
508 if (s.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700509 s.tracker.setBound(true, mAm.mProcessTracker.getMemFactorLocked(),
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700510 s.lastActivity);
511 }
512 }
513 }
514
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700515 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
516 ConnectionRecord c = new ConnectionRecord(b, activity,
517 connection, flags, clientLabel, clientIntent);
518
519 IBinder binder = connection.asBinder();
520 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
521 if (clist == null) {
522 clist = new ArrayList<ConnectionRecord>();
523 s.connections.put(binder, clist);
524 }
525 clist.add(c);
526 b.connections.add(c);
527 if (activity != null) {
528 if (activity.connections == null) {
529 activity.connections = new HashSet<ConnectionRecord>();
530 }
531 activity.connections.add(c);
532 }
533 b.client.connections.add(c);
534 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
535 b.client.hasAboveClient = true;
536 }
537 clist = mServiceConnections.get(binder);
538 if (clist == null) {
539 clist = new ArrayList<ConnectionRecord>();
540 mServiceConnections.put(binder, clist);
541 }
542 clist.add(c);
543
544 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
545 s.lastActivity = SystemClock.uptimeMillis();
Dianne Hackbornc0bd7472012-10-09 14:00:30 -0700546 if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700547 return 0;
548 }
549 }
550
551 if (s.app != null) {
552 // This could have made the service more important.
553 mAm.updateOomAdjLocked(s.app);
554 }
555
556 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
557 + ": received=" + b.intent.received
558 + " apps=" + b.intent.apps.size()
559 + " doRebind=" + b.intent.doRebind);
560
561 if (s.app != null && b.intent.received) {
562 // Service is already running, so we can immediately
563 // publish the connection.
564 try {
565 c.conn.connected(s.name, b.intent.binder);
566 } catch (Exception e) {
567 Slog.w(TAG, "Failure sending service " + s.shortName
568 + " to connection " + c.conn.asBinder()
569 + " (in " + c.binding.client.processName + ")", e);
570 }
571
572 // If this is the first app connected back to this binding,
573 // and the service had previously asked to be told when
574 // rebound, then do so.
575 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
576 requestServiceBindingLocked(s, b.intent, true);
577 }
578 } else if (!b.intent.requested) {
579 requestServiceBindingLocked(s, b.intent, false);
580 }
581 } finally {
582 Binder.restoreCallingIdentity(origId);
583 }
584
585 return 1;
586 }
587
588 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
589 final long origId = Binder.clearCallingIdentity();
590 try {
591 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
592 + " " + intent + ": " + service);
593 if (r != null) {
594 Intent.FilterComparison filter
595 = new Intent.FilterComparison(intent);
596 IntentBindRecord b = r.bindings.get(filter);
597 if (b != null && !b.received) {
598 b.binder = service;
599 b.requested = true;
600 b.received = true;
Dianne Hackborn390517b2013-05-30 15:03:32 -0700601 for (int conni=r.connections.size()-1; conni>=0; conni--) {
602 ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
603 for (int i=0; i<clist.size(); i++) {
604 ConnectionRecord c = clist.get(i);
605 if (!filter.equals(c.binding.intent.intent)) {
606 if (DEBUG_SERVICE) Slog.v(
607 TAG, "Not publishing to: " + c);
608 if (DEBUG_SERVICE) Slog.v(
609 TAG, "Bound intent: " + c.binding.intent.intent);
610 if (DEBUG_SERVICE) Slog.v(
611 TAG, "Published intent: " + intent);
612 continue;
613 }
614 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
615 try {
616 c.conn.connected(r.name, service);
617 } catch (Exception e) {
618 Slog.w(TAG, "Failure sending service " + r.name +
619 " to connection " + c.conn.asBinder() +
620 " (in " + c.binding.client.processName + ")", e);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700621 }
622 }
623 }
624 }
625
626 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
627 }
628 } finally {
629 Binder.restoreCallingIdentity(origId);
630 }
631 }
632
633 boolean unbindServiceLocked(IServiceConnection connection) {
634 IBinder binder = connection.asBinder();
635 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
636 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
637 if (clist == null) {
638 Slog.w(TAG, "Unbind failed: could not find connection for "
639 + connection.asBinder());
640 return false;
641 }
642
643 final long origId = Binder.clearCallingIdentity();
644 try {
645 while (clist.size() > 0) {
646 ConnectionRecord r = clist.get(0);
647 removeConnectionLocked(r, null, null);
648
649 if (r.binding.service.app != null) {
650 // This could have made the service less important.
651 mAm.updateOomAdjLocked(r.binding.service.app);
652 }
653 }
654 } finally {
655 Binder.restoreCallingIdentity(origId);
656 }
657
658 return true;
659 }
660
661 void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) {
662 final long origId = Binder.clearCallingIdentity();
663 try {
664 if (r != null) {
665 Intent.FilterComparison filter
666 = new Intent.FilterComparison(intent);
667 IntentBindRecord b = r.bindings.get(filter);
668 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
669 + " at " + b + ": apps="
670 + (b != null ? b.apps.size() : 0));
671
672 boolean inStopping = mStoppingServices.contains(r);
673 if (b != null) {
674 if (b.apps.size() > 0 && !inStopping) {
675 // Applications have already bound since the last
676 // unbind, so just rebind right here.
677 requestServiceBindingLocked(r, b, true);
678 } else {
679 // Note to tell the service the next time there is
680 // a new client.
681 b.doRebind = true;
682 }
683 }
684
685 serviceDoneExecutingLocked(r, inStopping);
686 }
687 } finally {
688 Binder.restoreCallingIdentity(origId);
689 }
690 }
691
692 private final ServiceRecord findServiceLocked(ComponentName name,
Dianne Hackborn41203752012-08-31 14:05:51 -0700693 IBinder token, int userId) {
694 ServiceRecord r = mServiceMap.getServiceByName(name, userId);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700695 return r == token ? r : null;
696 }
697
698 private final class ServiceLookupResult {
699 final ServiceRecord record;
700 final String permission;
701
702 ServiceLookupResult(ServiceRecord _record, String _permission) {
703 record = _record;
704 permission = _permission;
705 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700706 }
707
708 private class ServiceRestarter implements Runnable {
709 private ServiceRecord mService;
710
711 void setService(ServiceRecord service) {
712 mService = service;
713 }
714
715 public void run() {
716 synchronized(mAm) {
717 performServiceRestartLocked(mService);
718 }
719 }
720 }
721
722 private ServiceLookupResult retrieveServiceLocked(Intent service,
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700723 String resolvedType, int callingPid, int callingUid, int userId,
724 boolean createIfNeeded) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700725 ServiceRecord r = null;
726 if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
727 + " type=" + resolvedType + " callingUid=" + callingUid);
728
Dianne Hackborn139748f2012-09-24 11:36:57 -0700729 userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700730 false, true, "service", null);
731
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700732 if (service.getComponent() != null) {
733 r = mServiceMap.getServiceByName(service.getComponent(), userId);
734 }
735 if (r == null) {
736 Intent.FilterComparison filter = new Intent.FilterComparison(service);
737 r = mServiceMap.getServiceByIntent(filter, userId);
738 }
739 if (r == null) {
740 try {
741 ResolveInfo rInfo =
742 AppGlobals.getPackageManager().resolveService(
743 service, resolvedType,
744 ActivityManagerService.STOCK_PM_FLAGS, userId);
745 ServiceInfo sInfo =
746 rInfo != null ? rInfo.serviceInfo : null;
747 if (sInfo == null) {
Amith Yamasani2b914652012-08-27 12:04:40 -0700748 Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700749 ": not found");
750 return null;
751 }
752 ComponentName name = new ComponentName(
753 sInfo.applicationInfo.packageName, sInfo.name);
754 if (userId > 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700755 if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
756 sInfo.name, sInfo.flags)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700757 userId = 0;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700758 }
759 sInfo = new ServiceInfo(sInfo);
760 sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
761 }
762 r = mServiceMap.getServiceByName(name, userId);
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700763 if (r == null && createIfNeeded) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700764 Intent.FilterComparison filter = new Intent.FilterComparison(
765 service.cloneFilter());
766 ServiceRestarter res = new ServiceRestarter();
767 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
768 BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
769 synchronized (stats) {
770 ss = stats.getServiceStatsLocked(
771 sInfo.applicationInfo.uid, sInfo.packageName,
772 sInfo.name);
773 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700774 ProcessTracker.ServiceState tracker = null;
775 if ((sInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
776 tracker = mAm.mProcessTracker.getServiceStateLocked(sInfo.packageName,
777 sInfo.applicationInfo.uid, sInfo.name);
778 }
779 r = new ServiceRecord(mAm, ss, name, filter, sInfo, res, tracker);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700780 res.setService(r);
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700781 mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
782 mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700783
784 // Make sure this component isn't in the pending list.
785 int N = mPendingServices.size();
786 for (int i=0; i<N; i++) {
787 ServiceRecord pr = mPendingServices.get(i);
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700788 if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
789 && pr.name.equals(name)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700790 mPendingServices.remove(i);
791 i--;
792 N--;
793 }
794 }
795 }
796 } catch (RemoteException ex) {
797 // pm is in same process, this will never happen.
798 }
799 }
800 if (r != null) {
801 if (mAm.checkComponentPermission(r.permission,
802 callingPid, callingUid, r.appInfo.uid, r.exported)
803 != PackageManager.PERMISSION_GRANTED) {
804 if (!r.exported) {
805 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
806 + " from pid=" + callingPid
807 + ", uid=" + callingUid
808 + " that is not exported from uid " + r.appInfo.uid);
809 return new ServiceLookupResult(null, "not exported from uid "
810 + r.appInfo.uid);
811 }
812 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
813 + " from pid=" + callingPid
814 + ", uid=" + callingUid
815 + " requires " + r.permission);
816 return new ServiceLookupResult(null, r.permission);
817 }
818 return new ServiceLookupResult(r, null);
819 }
820 return null;
821 }
822
823 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
824 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
825 + why + " of " + r + " in app " + r.app);
826 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
827 + why + " of " + r.shortName);
828 long now = SystemClock.uptimeMillis();
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700829 if (r.executeNesting == 0) {
830 if (r.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700831 r.tracker.setExecuting(true, mAm.mProcessTracker.getMemFactorLocked(), now);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700832 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700833 if (r.app != null) {
834 if (r.app.executingServices.size() == 0) {
835 Message msg = mAm.mHandler.obtainMessage(
836 ActivityManagerService.SERVICE_TIMEOUT_MSG);
837 msg.obj = r.app;
838 mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
839 }
840 r.app.executingServices.add(r);
841 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700842 }
843 r.executeNesting++;
844 r.executingStart = now;
845 }
846
847 private final boolean requestServiceBindingLocked(ServiceRecord r,
848 IntentBindRecord i, boolean rebind) {
849 if (r.app == null || r.app.thread == null) {
850 // If service is not currently running, can't yet bind.
851 return false;
852 }
853 if ((!i.requested || rebind) && i.apps.size() > 0) {
854 try {
855 bumpServiceExecutingLocked(r, "bind");
Dianne Hackborna413dc02013-07-12 12:02:55 -0700856 r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
857 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
858 r.app.repProcState);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700859 if (!rebind) {
860 i.requested = true;
861 }
862 i.hasBound = true;
863 i.doRebind = false;
864 } catch (RemoteException e) {
865 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
866 return false;
867 }
868 }
869 return true;
870 }
871
872 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
873 boolean allowCancel) {
874 boolean canceled = false;
875
876 final long now = SystemClock.uptimeMillis();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700877
878 if ((r.serviceInfo.applicationInfo.flags
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700879 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
880 long minDuration = SERVICE_RESTART_DURATION;
881 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700882
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700883 // Any delivered but not yet finished starts should be put back
884 // on the pending list.
885 final int N = r.deliveredStarts.size();
886 if (N > 0) {
887 for (int i=N-1; i>=0; i--) {
888 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
889 si.removeUriPermissionsLocked();
890 if (si.intent == null) {
891 // We'll generate this again if needed.
892 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
893 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
894 r.pendingStarts.add(0, si);
895 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
896 dur *= 2;
897 if (minDuration < dur) minDuration = dur;
898 if (resetTime < dur) resetTime = dur;
899 } else {
900 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
901 + r.name);
902 canceled = true;
903 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700904 }
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700905 r.deliveredStarts.clear();
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700906 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700907
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700908 r.totalRestartCount++;
909 if (r.restartDelay == 0) {
910 r.restartCount++;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700911 r.restartDelay = minDuration;
912 } else {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700913 // If it has been a "reasonably long time" since the service
914 // was started, then reset our restart duration back to
915 // the beginning, so we don't infinitely increase the duration
916 // on a service that just occasionally gets killed (which is
917 // a normal case, due to process being killed to reclaim memory).
918 if (now > (r.restartTime+resetTime)) {
919 r.restartCount = 1;
920 r.restartDelay = minDuration;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700921 } else {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700922 if ((r.serviceInfo.applicationInfo.flags
923 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
924 // Services in peristent processes will restart much more
925 // quickly, since they are pretty important. (Think SystemUI).
926 r.restartDelay += minDuration/2;
927 } else {
928 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
929 if (r.restartDelay < minDuration) {
930 r.restartDelay = minDuration;
931 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700932 }
933 }
934 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700935
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700936 r.nextRestartTime = now + r.restartDelay;
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700937
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700938 // Make sure that we don't end up restarting a bunch of services
939 // all at the same time.
940 boolean repeat;
941 do {
942 repeat = false;
943 for (int i=mRestartingServices.size()-1; i>=0; i--) {
944 ServiceRecord r2 = mRestartingServices.get(i);
945 if (r2 != r && r.nextRestartTime
946 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
947 && r.nextRestartTime
948 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
949 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
950 r.restartDelay = r.nextRestartTime - now;
951 repeat = true;
952 break;
953 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700954 }
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -0700955 } while (repeat);
956
957 } else {
958 // Persistent processes are immediately restrted, so there is no
959 // reason to hold of on restarting their services.
960 r.totalRestartCount++;
961 r.restartCount = 0;
962 r.restartDelay = 0;
963 r.nextRestartTime = now;
964 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700965
966 if (!mRestartingServices.contains(r)) {
967 mRestartingServices.add(r);
968 }
969
970 r.cancelNotification();
971
972 mAm.mHandler.removeCallbacks(r.restarter);
973 mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
974 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
975 Slog.w(TAG, "Scheduling restart of crashed service "
976 + r.shortName + " in " + r.restartDelay + "ms");
977 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700978 r.userId, r.shortName, r.restartDelay);
Dianne Hackborn599db5c2012-08-03 19:28:48 -0700979
980 return canceled;
981 }
982
983 final void performServiceRestartLocked(ServiceRecord r) {
984 if (!mRestartingServices.contains(r)) {
985 return;
986 }
987 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
988 }
989
990 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
991 if (r.restartDelay == 0) {
992 return false;
993 }
994 r.resetRestartCounter();
995 mRestartingServices.remove(r);
996 mAm.mHandler.removeCallbacks(r.restarter);
997 return true;
998 }
999
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001000 private final String bringUpServiceLocked(ServiceRecord r,
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001001 int intentFlags, boolean whileRestarting) {
1002 //Slog.i(TAG, "Bring up service:");
1003 //r.dump(" ");
1004
1005 if (r.app != null && r.app.thread != null) {
1006 sendServiceArgsLocked(r, false);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001007 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001008 }
1009
1010 if (!whileRestarting && r.restartDelay > 0) {
1011 // If waiting for a restart, then do nothing.
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001012 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001013 }
1014
1015 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
1016
1017 // We are now bringing the service up, so no longer in the
1018 // restarting state.
1019 mRestartingServices.remove(r);
1020
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001021 // Make sure that the user who owns this service is started. If not,
1022 // we don't want to allow it to run.
1023 if (mAm.mStartedUsers.get(r.userId) == null) {
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001024 String msg = "Unable to launch app "
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001025 + r.appInfo.packageName + "/"
1026 + r.appInfo.uid + " for service "
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001027 + r.intent.getIntent() + ": user " + r.userId + " is stopped";
1028 Slog.w(TAG, msg);
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001029 bringDownServiceLocked(r);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001030 return msg;
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001031 }
1032
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001033 // Service is now being launched, its package can't be stopped.
1034 try {
1035 AppGlobals.getPackageManager().setPackageStoppedState(
1036 r.packageName, false, r.userId);
1037 } catch (RemoteException e) {
1038 } catch (IllegalArgumentException e) {
1039 Slog.w(TAG, "Failed trying to unstop package "
1040 + r.packageName + ": " + e);
1041 }
1042
1043 final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
1044 final String procName = r.processName;
1045 ProcessRecord app;
1046
1047 if (!isolated) {
1048 app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
1049 if (DEBUG_MU)
1050 Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
1051 if (app != null && app.thread != null) {
1052 try {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001053 app.addPackage(r.appInfo.packageName, mAm.mProcessTracker);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001054 realStartServiceLocked(r, app);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001055 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001056 } catch (RemoteException e) {
1057 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
1058 }
1059
1060 // If a dead object exception was thrown -- fall through to
1061 // restart the application.
1062 }
1063 } else {
1064 // If this service runs in an isolated process, then each time
1065 // we call startProcessLocked() we will get a new isolated
1066 // process, starting another process if we are currently waiting
1067 // for a previous process to come up. To deal with this, we store
1068 // in the service any current isolated process it is running in or
1069 // waiting to have come up.
1070 app = r.isolatedProc;
1071 }
1072
1073 // Not running -- get it started, and enqueue this service record
1074 // to be executed when the app comes up.
1075 if (app == null) {
1076 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
1077 "service", r.name, false, isolated)) == null) {
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001078 String msg = "Unable to launch app "
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001079 + r.appInfo.packageName + "/"
1080 + r.appInfo.uid + " for service "
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001081 + r.intent.getIntent() + ": process is bad";
1082 Slog.w(TAG, msg);
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001083 bringDownServiceLocked(r);
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001084 return msg;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001085 }
1086 if (isolated) {
1087 r.isolatedProc = app;
1088 }
1089 }
1090
1091 if (!mPendingServices.contains(r)) {
1092 mPendingServices.add(r);
1093 }
1094
Dianne Hackbornc0bd7472012-10-09 14:00:30 -07001095 return null;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001096 }
1097
1098 private final void requestServiceBindingsLocked(ServiceRecord r) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07001099 for (int i=r.bindings.size()-1; i>=0; i--) {
1100 IntentBindRecord ibr = r.bindings.valueAt(i);
1101 if (!requestServiceBindingLocked(r, ibr, false)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001102 break;
1103 }
1104 }
1105 }
1106
1107 private final void realStartServiceLocked(ServiceRecord r,
1108 ProcessRecord app) throws RemoteException {
1109 if (app.thread == null) {
1110 throw new RemoteException();
1111 }
1112 if (DEBUG_MU)
1113 Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
1114 + ", ProcessRecord.uid = " + app.uid);
1115 r.app = app;
1116 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
1117
1118 app.services.add(r);
1119 bumpServiceExecutingLocked(r, "create");
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001120 mAm.updateLruProcessLocked(app, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001121
1122 boolean created = false;
1123 try {
Dianne Hackborncf1171642013-07-12 17:26:02 -07001124 String nameTerm;
1125 int lastPeriod = r.shortName.lastIndexOf('.');
1126 nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
Jeff Sharkey9d6d8902012-11-09 17:32:43 -08001127 EventLogTags.writeAmCreateService(
Dianne Hackborncf1171642013-07-12 17:26:02 -07001128 r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001129 synchronized (r.stats.getBatteryStats()) {
1130 r.stats.startLaunchedLocked();
1131 }
1132 mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborna413dc02013-07-12 12:02:55 -07001133 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001134 app.thread.scheduleCreateService(r, r.serviceInfo,
Dianne Hackborna413dc02013-07-12 12:02:55 -07001135 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
1136 app.repProcState);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001137 r.postNotification();
1138 created = true;
1139 } finally {
1140 if (!created) {
1141 app.services.remove(r);
1142 scheduleServiceRestartLocked(r, false);
1143 }
1144 }
1145
1146 requestServiceBindingsLocked(r);
1147
1148 // If the service is in the started state, and there are no
1149 // pending arguments, then fake up one so its onStartCommand() will
1150 // be called.
1151 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
1152 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
1153 null, null));
1154 }
1155
1156 sendServiceArgsLocked(r, true);
1157 }
1158
1159 private final void sendServiceArgsLocked(ServiceRecord r,
1160 boolean oomAdjusted) {
1161 final int N = r.pendingStarts.size();
1162 if (N == 0) {
1163 return;
1164 }
1165
1166 while (r.pendingStarts.size() > 0) {
1167 try {
1168 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
1169 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
1170 + r + " " + r.intent + " args=" + si.intent);
1171 if (si.intent == null && N > 1) {
1172 // If somehow we got a dummy null intent in the middle,
1173 // then skip it. DO NOT skip a null intent when it is
1174 // the only one in the list -- this is to support the
1175 // onStartCommand(null) case.
1176 continue;
1177 }
1178 si.deliveredTime = SystemClock.uptimeMillis();
1179 r.deliveredStarts.add(si);
1180 si.deliveryCount++;
1181 if (si.neededGrants != null) {
1182 mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
1183 si.getUriPermissionsLocked());
1184 }
1185 bumpServiceExecutingLocked(r, "start");
1186 if (!oomAdjusted) {
1187 oomAdjusted = true;
1188 mAm.updateOomAdjLocked(r.app);
1189 }
1190 int flags = 0;
1191 if (si.deliveryCount > 1) {
1192 flags |= Service.START_FLAG_RETRY;
1193 }
1194 if (si.doneExecutingCount > 0) {
1195 flags |= Service.START_FLAG_REDELIVERY;
1196 }
1197 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
1198 } catch (RemoteException e) {
1199 // Remote process gone... we'll let the normal cleanup take
1200 // care of this.
1201 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
1202 break;
1203 } catch (Exception e) {
1204 Slog.w(TAG, "Unexpected exception", e);
1205 break;
1206 }
1207 }
1208 }
1209
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001210 private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
1211 boolean hasConn) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001212 //Slog.i(TAG, "Bring down service:");
1213 //r.dump(" ");
1214
1215 // Does it still need to run?
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001216 if (r.startRequested) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001217 return;
1218 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001219
1220 if (!knowConn) {
1221 hasConn = r.hasAutoCreateConnections();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001222 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001223 if (hasConn) {
1224 return;
1225 }
1226
1227 bringDownServiceLocked(r);
1228 }
1229
1230 private final void bringDownServiceLocked(ServiceRecord r) {
1231 //Slog.i(TAG, "Bring down service:");
1232 //r.dump(" ");
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001233
Dianne Hackborn390517b2013-05-30 15:03:32 -07001234 // Report to all of the connections that the service is no longer
1235 // available.
1236 for (int conni=r.connections.size()-1; conni>=0; conni--) {
1237 ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
1238 for (int i=0; i<c.size(); i++) {
1239 ConnectionRecord cr = c.get(i);
1240 // There is still a connection to the service that is
1241 // being brought down. Mark it as dead.
1242 cr.serviceDead = true;
1243 try {
1244 cr.conn.connected(r.name, null);
1245 } catch (Exception e) {
1246 Slog.w(TAG, "Failure disconnecting service " + r.name +
1247 " to connection " + c.get(i).conn.asBinder() +
1248 " (in " + c.get(i).binding.client.processName + ")", e);
1249 }
1250 }
1251 }
1252
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001253 // Tell the service that it has been unbound.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001254 if (r.app != null && r.app.thread != null) {
1255 for (int i=r.bindings.size()-1; i>=0; i--) {
1256 IntentBindRecord ibr = r.bindings.valueAt(i);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001257 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
1258 + ": hasBound=" + ibr.hasBound);
Dianne Hackborn390517b2013-05-30 15:03:32 -07001259 if (ibr.hasBound) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001260 try {
1261 bumpServiceExecutingLocked(r, "bring down unbind");
1262 mAm.updateOomAdjLocked(r.app);
1263 ibr.hasBound = false;
1264 r.app.thread.scheduleUnbindService(r,
1265 ibr.intent.getIntent());
1266 } catch (Exception e) {
1267 Slog.w(TAG, "Exception when unbinding service "
1268 + r.shortName, e);
1269 serviceDoneExecutingLocked(r, true);
1270 }
1271 }
1272 }
1273 }
1274
1275 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Jeff Sharkey9d6d8902012-11-09 17:32:43 -08001276 EventLogTags.writeAmDestroyService(
1277 r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001278
1279 mServiceMap.removeServiceByName(r.name, r.userId);
1280 mServiceMap.removeServiceByIntent(r.intent, r.userId);
1281 r.totalRestartCount = 0;
1282 unscheduleServiceRestartLocked(r);
1283
1284 // Also make sure it is not on the pending list.
1285 int N = mPendingServices.size();
1286 for (int i=0; i<N; i++) {
1287 if (mPendingServices.get(i) == r) {
1288 mPendingServices.remove(i);
1289 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
1290 i--;
1291 N--;
1292 }
1293 }
1294
1295 r.cancelNotification();
1296 r.isForeground = false;
1297 r.foregroundId = 0;
1298 r.foregroundNoti = null;
1299
1300 // Clear start entries.
1301 r.clearDeliveredStartsLocked();
1302 r.pendingStarts.clear();
1303
1304 if (r.app != null) {
1305 synchronized (r.stats.getBatteryStats()) {
1306 r.stats.stopLaunchedLocked();
1307 }
1308 r.app.services.remove(r);
1309 if (r.app.thread != null) {
1310 try {
1311 bumpServiceExecutingLocked(r, "stop");
1312 mStoppingServices.add(r);
1313 mAm.updateOomAdjLocked(r.app);
1314 r.app.thread.scheduleStopService(r);
1315 } catch (Exception e) {
1316 Slog.w(TAG, "Exception when stopping service "
1317 + r.shortName, e);
1318 serviceDoneExecutingLocked(r, true);
1319 }
1320 updateServiceForegroundLocked(r.app, false);
1321 } else {
1322 if (DEBUG_SERVICE) Slog.v(
1323 TAG, "Removed service that has no process: " + r);
1324 }
1325 } else {
1326 if (DEBUG_SERVICE) Slog.v(
1327 TAG, "Removed service that is not running: " + r);
1328 }
1329
1330 if (r.bindings.size() > 0) {
1331 r.bindings.clear();
1332 }
1333
1334 if (r.restarter instanceof ServiceRestarter) {
1335 ((ServiceRestarter)r.restarter).setService(null);
1336 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001337
Dianne Hackborn904a8572013-06-28 18:12:31 -07001338 int memFactor = mAm.mProcessTracker.getMemFactorLocked();
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001339 long now = SystemClock.uptimeMillis();
1340 if (r.tracker != null) {
1341 r.tracker.setStarted(false, memFactor, now);
1342 r.tracker.setBound(false, memFactor, now);
1343 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001344 }
1345
1346 void removeConnectionLocked(
1347 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
1348 IBinder binder = c.conn.asBinder();
1349 AppBindRecord b = c.binding;
1350 ServiceRecord s = b.service;
1351 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
1352 if (clist != null) {
1353 clist.remove(c);
1354 if (clist.size() == 0) {
1355 s.connections.remove(binder);
1356 }
1357 }
1358 b.connections.remove(c);
1359 if (c.activity != null && c.activity != skipAct) {
1360 if (c.activity.connections != null) {
1361 c.activity.connections.remove(c);
1362 }
1363 }
1364 if (b.client != skipApp) {
1365 b.client.connections.remove(c);
1366 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
1367 b.client.updateHasAboveClientLocked();
1368 }
1369 }
1370 clist = mServiceConnections.get(binder);
1371 if (clist != null) {
1372 clist.remove(c);
1373 if (clist.size() == 0) {
1374 mServiceConnections.remove(binder);
1375 }
1376 }
1377
1378 if (b.connections.size() == 0) {
1379 b.intent.apps.remove(b.client);
1380 }
1381
1382 if (!c.serviceDead) {
1383 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
1384 + ": shouldUnbind=" + b.intent.hasBound);
1385 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
1386 && b.intent.hasBound) {
1387 try {
1388 bumpServiceExecutingLocked(s, "unbind");
1389 mAm.updateOomAdjLocked(s.app);
1390 b.intent.hasBound = false;
1391 // Assume the client doesn't want to know about a rebind;
1392 // we will deal with that later if it asks for one.
1393 b.intent.doRebind = false;
1394 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
1395 } catch (Exception e) {
1396 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
1397 serviceDoneExecutingLocked(s, true);
1398 }
1399 }
1400
1401 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001402 boolean hasAutoCreate = s.hasAutoCreateConnections();
1403 if (!hasAutoCreate) {
1404 if (s.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07001405 s.tracker.setBound(false, mAm.mProcessTracker.getMemFactorLocked(),
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001406 SystemClock.uptimeMillis());
1407 }
1408 }
1409 bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001410 }
1411 }
1412 }
1413
1414 void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
1415 boolean inStopping = mStoppingServices.contains(r);
1416 if (r != null) {
1417 if (type == 1) {
1418 // This is a call from a service start... take care of
1419 // book-keeping.
1420 r.callStart = true;
1421 switch (res) {
1422 case Service.START_STICKY_COMPATIBILITY:
1423 case Service.START_STICKY: {
1424 // We are done with the associated start arguments.
1425 r.findDeliveredStart(startId, true);
1426 // Don't stop if killed.
1427 r.stopIfKilled = false;
1428 break;
1429 }
1430 case Service.START_NOT_STICKY: {
1431 // We are done with the associated start arguments.
1432 r.findDeliveredStart(startId, true);
1433 if (r.getLastStartId() == startId) {
1434 // There is no more work, and this service
1435 // doesn't want to hang around if killed.
1436 r.stopIfKilled = true;
1437 }
1438 break;
1439 }
1440 case Service.START_REDELIVER_INTENT: {
1441 // We'll keep this item until they explicitly
1442 // call stop for it, but keep track of the fact
1443 // that it was delivered.
1444 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
1445 if (si != null) {
1446 si.deliveryCount = 0;
1447 si.doneExecutingCount++;
1448 // Don't stop if killed.
1449 r.stopIfKilled = true;
1450 }
1451 break;
1452 }
1453 case Service.START_TASK_REMOVED_COMPLETE: {
1454 // Special processing for onTaskRemoved(). Don't
1455 // impact normal onStartCommand() processing.
1456 r.findDeliveredStart(startId, true);
1457 break;
1458 }
1459 default:
1460 throw new IllegalArgumentException(
1461 "Unknown service start result: " + res);
1462 }
1463 if (res == Service.START_STICKY_COMPATIBILITY) {
1464 r.callStart = false;
1465 }
1466 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001467 final long origId = Binder.clearCallingIdentity();
1468 serviceDoneExecutingLocked(r, inStopping);
1469 Binder.restoreCallingIdentity(origId);
1470 } else {
1471 Slog.w(TAG, "Done executing unknown service from pid "
1472 + Binder.getCallingPid());
1473 }
1474 }
1475
1476 private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
1477 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
1478 + ": nesting=" + r.executeNesting
1479 + ", inStopping=" + inStopping + ", app=" + r.app);
1480 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
1481 r.executeNesting--;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001482 if (r.executeNesting <= 0) {
1483 if (r.app != null) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001484 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001485 "Nesting at 0 of " + r.shortName);
1486 r.app.executingServices.remove(r);
1487 if (r.app.executingServices.size() == 0) {
1488 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
1489 "No more executingServices of " + r.shortName);
1490 mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
1491 }
1492 if (inStopping) {
1493 if (DEBUG_SERVICE) Slog.v(TAG,
1494 "doneExecuting remove stopping " + r);
1495 mStoppingServices.remove(r);
1496 r.bindings.clear();
1497 }
1498 mAm.updateOomAdjLocked(r.app);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001499 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001500 if (r.tracker != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07001501 r.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactorLocked(),
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001502 SystemClock.uptimeMillis());
1503 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001504 }
1505 }
1506
1507 boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
1508 boolean didSomething = false;
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -07001509 // Collect any services that are waiting for this process to come up.
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001510 if (mPendingServices.size() > 0) {
1511 ServiceRecord sr = null;
1512 try {
1513 for (int i=0; i<mPendingServices.size(); i++) {
1514 sr = mPendingServices.get(i);
1515 if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
1516 || !processName.equals(sr.processName))) {
1517 continue;
1518 }
1519
1520 mPendingServices.remove(i);
1521 i--;
Jim Miller95129532013-06-12 14:18:07 -07001522 proc.addPackage(sr.appInfo.packageName, mAm.mProcessTracker);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001523 realStartServiceLocked(sr, proc);
1524 didSomething = true;
1525 }
1526 } catch (Exception e) {
1527 Slog.w(TAG, "Exception in new application when starting service "
1528 + sr.shortName, e);
1529 throw e;
1530 }
1531 }
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -07001532 // Also, if there are any services that are waiting to restart and
1533 // would run in this process, now is a good time to start them. It would
1534 // be weird to bring up the process but arbitrarily not let the services
1535 // run at this point just because their restart time hasn't come up.
1536 if (mRestartingServices.size() > 0) {
1537 ServiceRecord sr = null;
1538 for (int i=0; i<mRestartingServices.size(); i++) {
1539 sr = mRestartingServices.get(i);
1540 if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
1541 || !processName.equals(sr.processName))) {
1542 continue;
1543 }
1544 mAm.mHandler.removeCallbacks(sr.restarter);
1545 mAm.mHandler.post(sr.restarter);
1546 }
1547 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001548 return didSomething;
1549 }
1550
1551 void processStartTimedOutLocked(ProcessRecord proc) {
1552 for (int i=0; i<mPendingServices.size(); i++) {
1553 ServiceRecord sr = mPendingServices.get(i);
1554 if ((proc.uid == sr.appInfo.uid
1555 && proc.processName.equals(sr.processName))
1556 || sr.isolatedProc == proc) {
1557 Slog.w(TAG, "Forcing bringing down service: " + sr);
1558 sr.isolatedProc = null;
1559 mPendingServices.remove(i);
1560 i--;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001561 bringDownServiceLocked(sr);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001562 }
1563 }
1564 }
1565
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001566 private boolean collectForceStopServicesLocked(String name, int userId,
1567 boolean evenPersistent, boolean doit,
1568 HashMap<ComponentName, ServiceRecord> services,
1569 ArrayList<ServiceRecord> result) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001570 boolean didSomething = false;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001571 for (ServiceRecord service : services.values()) {
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001572 if ((name == null || service.packageName.equals(name))
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001573 && (service.app == null || evenPersistent || !service.app.persistent)) {
1574 if (!doit) {
1575 return true;
1576 }
1577 didSomething = true;
1578 Slog.i(TAG, " Force stopping service " + service);
1579 if (service.app != null) {
1580 service.app.removed = true;
1581 }
1582 service.app = null;
1583 service.isolatedProc = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001584 result.add(service);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001585 }
1586 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001587 return didSomething;
1588 }
1589
1590 boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
1591 boolean didSomething = false;
1592 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
1593 if (userId == UserHandle.USER_ALL) {
1594 for (int i=0; i<mServiceMap.mServicesByNamePerUser.size(); i++) {
1595 didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
1596 doit, mServiceMap.mServicesByNamePerUser.valueAt(i), services);
1597 if (!doit && didSomething) {
1598 return true;
1599 }
1600 }
1601 } else {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001602 HashMap<ComponentName, ServiceRecord> items
1603 = mServiceMap.mServicesByNamePerUser.get(userId);
1604 if (items != null) {
1605 didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
1606 doit, items, services);
1607 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001608 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001609
1610 int N = services.size();
1611 for (int i=0; i<N; i++) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001612 bringDownServiceLocked(services.get(i));
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001613 }
1614 return didSomething;
1615 }
1616
1617 void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
1618 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
1619 for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
1620 if (sr.packageName.equals(component.getPackageName())) {
1621 services.add(sr);
1622 }
1623 }
1624
1625 // Take care of any running services associated with the app.
1626 for (int i=0; i<services.size(); i++) {
1627 ServiceRecord sr = services.get(i);
1628 if (sr.startRequested) {
1629 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
1630 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
1631 stopServiceLocked(sr);
1632 } else {
1633 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
1634 sr.makeNextStartId(), baseIntent, null));
1635 if (sr.app != null && sr.app.thread != null) {
1636 sendServiceArgsLocked(sr, false);
1637 }
1638 }
1639 }
1640 }
1641 }
1642
1643 final void killServicesLocked(ProcessRecord app,
1644 boolean allowRestart) {
1645 // Report disconnected services.
1646 if (false) {
1647 // XXX we are letting the client link to the service for
1648 // death notifications.
1649 if (app.services.size() > 0) {
1650 Iterator<ServiceRecord> it = app.services.iterator();
1651 while (it.hasNext()) {
1652 ServiceRecord r = it.next();
Dianne Hackborn390517b2013-05-30 15:03:32 -07001653 for (int conni=r.connections.size()-1; conni>=0; conni--) {
1654 ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
1655 for (int i=0; i<cl.size(); i++) {
1656 ConnectionRecord c = cl.get(i);
1657 if (c.binding.client != app) {
1658 try {
1659 //c.conn.connected(r.className, null);
1660 } catch (Exception e) {
1661 // todo: this should be asynchronous!
1662 Slog.w(TAG, "Exception thrown disconnected servce "
1663 + r.shortName
1664 + " from app " + app.processName, e);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001665 }
1666 }
1667 }
1668 }
1669 }
1670 }
1671 }
1672
1673 // Clean up any connections this application has to other services.
Dianne Hackbornc8230512013-07-13 21:32:12 -07001674 for (int i=app.connections.size()-1; i>=0; i--) {
1675 ConnectionRecord r = app.connections.valueAt(i);
1676 removeConnectionLocked(r, app, null);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001677 }
1678 app.connections.clear();
1679
Dianne Hackbornc8230512013-07-13 21:32:12 -07001680 for (int i=app.services.size()-1; i>=0; i--) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001681 // Any services running in the application need to be placed
1682 // back in the pending list.
Dianne Hackbornc8230512013-07-13 21:32:12 -07001683 ServiceRecord sr = app.services.valueAt(i);
1684 synchronized (sr.stats.getBatteryStats()) {
1685 sr.stats.stopLaunchedLocked();
1686 }
1687 sr.app = null;
1688 sr.isolatedProc = null;
1689 sr.executeNesting = 0;
1690 if (sr.tracker != null) {
1691 sr.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactorLocked(),
1692 SystemClock.uptimeMillis());
1693 }
1694 if (mStoppingServices.remove(sr)) {
1695 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
1696 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001697
Dianne Hackbornc8230512013-07-13 21:32:12 -07001698 final int numClients = sr.bindings.size();
1699 for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
1700 IntentBindRecord b = sr.bindings.valueAt(bindingi);
1701 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
1702 + ": shouldUnbind=" + b.hasBound);
1703 b.binder = null;
1704 b.requested = b.received = b.hasBound = false;
1705 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001706
Dianne Hackbornc8230512013-07-13 21:32:12 -07001707 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
1708 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
1709 Slog.w(TAG, "Service crashed " + sr.crashCount
1710 + " times, stopping: " + sr);
1711 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
1712 sr.userId, sr.crashCount, sr.shortName, app.pid);
1713 bringDownServiceLocked(sr);
1714 } else if (!allowRestart) {
1715 bringDownServiceLocked(sr);
1716 } else {
1717 boolean canceled = scheduleServiceRestartLocked(sr, true);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001718
Dianne Hackbornc8230512013-07-13 21:32:12 -07001719 // Should the service remain running? Note that in the
1720 // extreme case of so many attempts to deliver a command
1721 // that it failed we also will stop it here.
1722 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
1723 if (sr.pendingStarts.size() == 0) {
1724 sr.startRequested = false;
1725 if (sr.tracker != null) {
1726 sr.tracker.setStarted(false, mAm.mProcessTracker.getMemFactorLocked(),
1727 SystemClock.uptimeMillis());
1728 }
1729 if (!sr.hasAutoCreateConnections()) {
1730 // Whoops, no reason to restart!
1731 bringDownServiceLocked(sr);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001732 }
1733 }
1734 }
1735 }
Dianne Hackbornc8230512013-07-13 21:32:12 -07001736 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001737
Dianne Hackbornc8230512013-07-13 21:32:12 -07001738 if (!allowRestart) {
1739 app.services.clear();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001740 }
1741
1742 // Make sure we have no more records on the stopping list.
1743 int i = mStoppingServices.size();
1744 while (i > 0) {
1745 i--;
1746 ServiceRecord sr = mStoppingServices.get(i);
1747 if (sr.app == app) {
1748 mStoppingServices.remove(i);
1749 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
1750 }
1751 }
1752
1753 app.executingServices.clear();
1754 }
1755
1756 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
1757 ActivityManager.RunningServiceInfo info =
1758 new ActivityManager.RunningServiceInfo();
1759 info.service = r.name;
1760 if (r.app != null) {
1761 info.pid = r.app.pid;
1762 }
1763 info.uid = r.appInfo.uid;
1764 info.process = r.processName;
1765 info.foreground = r.isForeground;
1766 info.activeSince = r.createTime;
1767 info.started = r.startRequested;
1768 info.clientCount = r.connections.size();
1769 info.crashCount = r.crashCount;
1770 info.lastActivityTime = r.lastActivity;
1771 if (r.isForeground) {
1772 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
1773 }
1774 if (r.startRequested) {
1775 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
1776 }
1777 if (r.app != null && r.app.pid == ActivityManagerService.MY_PID) {
1778 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
1779 }
1780 if (r.app != null && r.app.persistent) {
1781 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
1782 }
1783
Dianne Hackborn390517b2013-05-30 15:03:32 -07001784 for (int conni=r.connections.size()-1; conni>=0; conni--) {
1785 ArrayList<ConnectionRecord> connl = r.connections.valueAt(conni);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001786 for (int i=0; i<connl.size(); i++) {
1787 ConnectionRecord conn = connl.get(i);
1788 if (conn.clientLabel != 0) {
1789 info.clientPackage = conn.binding.client.info.packageName;
1790 info.clientLabel = conn.clientLabel;
1791 return info;
1792 }
1793 }
1794 }
1795 return info;
1796 }
1797
1798 List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum,
1799 int flags) {
1800 ArrayList<ActivityManager.RunningServiceInfo> res
1801 = new ArrayList<ActivityManager.RunningServiceInfo>();
1802
Dianne Hackborn0c380492012-08-20 17:23:30 -07001803 final int uid = Binder.getCallingUid();
1804 final long ident = Binder.clearCallingIdentity();
1805 try {
1806 if (ActivityManager.checkUidPermission(
1807 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1808 uid) == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn1676c852012-09-10 14:52:30 -07001809 int[] users = mAm.getUsersLocked();
1810 for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
1811 if (mServiceMap.getAllServices(users[ui]).size() > 0) {
Dianne Hackborn0c380492012-08-20 17:23:30 -07001812 Iterator<ServiceRecord> it = mServiceMap.getAllServices(
Dianne Hackborn1676c852012-09-10 14:52:30 -07001813 users[ui]).iterator();
Dianne Hackborn0c380492012-08-20 17:23:30 -07001814 while (it.hasNext() && res.size() < maxNum) {
1815 res.add(makeRunningServiceInfoLocked(it.next()));
1816 }
1817 }
1818 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001819
Dianne Hackborn0c380492012-08-20 17:23:30 -07001820 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
1821 ServiceRecord r = mRestartingServices.get(i);
1822 ActivityManager.RunningServiceInfo info =
1823 makeRunningServiceInfoLocked(r);
1824 info.restarting = r.nextRestartTime;
1825 res.add(info);
1826 }
1827 } else {
1828 int userId = UserHandle.getUserId(uid);
1829 if (mServiceMap.getAllServices(userId).size() > 0) {
1830 Iterator<ServiceRecord> it
1831 = mServiceMap.getAllServices(userId).iterator();
1832 while (it.hasNext() && res.size() < maxNum) {
1833 res.add(makeRunningServiceInfoLocked(it.next()));
1834 }
1835 }
1836
1837 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
1838 ServiceRecord r = mRestartingServices.get(i);
1839 if (r.userId == userId) {
1840 ActivityManager.RunningServiceInfo info =
1841 makeRunningServiceInfoLocked(r);
1842 info.restarting = r.nextRestartTime;
1843 res.add(info);
1844 }
1845 }
1846 }
1847 } finally {
1848 Binder.restoreCallingIdentity(ident);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001849 }
1850
1851 return res;
1852 }
1853
1854 public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001855 int userId = UserHandle.getUserId(Binder.getCallingUid());
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001856 ServiceRecord r = mServiceMap.getServiceByName(name, userId);
1857 if (r != null) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07001858 for (int conni=r.connections.size()-1; conni>=0; conni--) {
1859 ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001860 for (int i=0; i<conn.size(); i++) {
1861 if (conn.get(i).clientIntent != null) {
1862 return conn.get(i).clientIntent;
1863 }
1864 }
1865 }
1866 }
1867 return null;
1868 }
1869
1870 void serviceTimeout(ProcessRecord proc) {
1871 String anrMessage = null;
1872
1873 synchronized(this) {
1874 if (proc.executingServices.size() == 0 || proc.thread == null) {
1875 return;
1876 }
1877 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001878 ServiceRecord timeout = null;
1879 long nextTime = 0;
Dianne Hackbornc8230512013-07-13 21:32:12 -07001880 for (int i=proc.executingServices.size()-1; i>=0; i--) {
1881 ServiceRecord sr = proc.executingServices.valueAt(i);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001882 if (sr.executingStart < maxTime) {
1883 timeout = sr;
1884 break;
1885 }
1886 if (sr.executingStart > nextTime) {
1887 nextTime = sr.executingStart;
1888 }
1889 }
1890 if (timeout != null && mAm.mLruProcesses.contains(proc)) {
1891 Slog.w(TAG, "Timeout executing service: " + timeout);
1892 anrMessage = "Executing service " + timeout.shortName;
1893 } else {
1894 Message msg = mAm.mHandler.obtainMessage(
1895 ActivityManagerService.SERVICE_TIMEOUT_MSG);
1896 msg.obj = proc;
1897 mAm.mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
1898 }
1899 }
1900
1901 if (anrMessage != null) {
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -07001902 mAm.appNotResponding(proc, null, null, false, anrMessage);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001903 }
1904 }
1905
1906 /**
1907 * Prints a list of ServiceRecords (dumpsys activity services)
1908 */
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07001909 void dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001910 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
1911 boolean needSep = false;
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07001912 boolean printedAnything = false;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001913
1914 ItemMatcher matcher = new ItemMatcher();
1915 matcher.build(args, opti);
1916
1917 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
1918 try {
Dianne Hackborn1676c852012-09-10 14:52:30 -07001919 int[] users = mAm.getUsersLocked();
1920 for (int user : users) {
1921 if (mServiceMap.getAllServices(user).size() > 0) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001922 boolean printed = false;
1923 long nowReal = SystemClock.elapsedRealtime();
1924 Iterator<ServiceRecord> it = mServiceMap.getAllServices(
Dianne Hackborn1676c852012-09-10 14:52:30 -07001925 user).iterator();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001926 needSep = false;
1927 while (it.hasNext()) {
1928 ServiceRecord r = it.next();
1929 if (!matcher.match(r, r.name)) {
1930 continue;
1931 }
1932 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
1933 continue;
1934 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07001935 printedAnything = true;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001936 if (!printed) {
Dianne Hackborn1676c852012-09-10 14:52:30 -07001937 if (user != 0) {
Dianne Hackbornf88dd0b2012-08-08 17:20:32 -07001938 pw.println();
1939 }
Dianne Hackborn1676c852012-09-10 14:52:30 -07001940 pw.println(" User " + user + " active services:");
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001941 printed = true;
1942 }
1943 if (needSep) {
1944 pw.println();
1945 }
1946 pw.print(" * ");
1947 pw.println(r);
1948 if (dumpAll) {
1949 r.dump(pw, " ");
1950 needSep = true;
1951 } else {
1952 pw.print(" app=");
1953 pw.println(r.app);
1954 pw.print(" created=");
1955 TimeUtils.formatDuration(r.createTime, nowReal, pw);
1956 pw.print(" started=");
1957 pw.print(r.startRequested);
1958 pw.print(" connections=");
1959 pw.println(r.connections.size());
1960 if (r.connections.size() > 0) {
1961 pw.println(" Connections:");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07001962 for (int conni=0; conni<r.connections.size(); conni++) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07001963 ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07001964 for (int i = 0; i < clist.size(); i++) {
1965 ConnectionRecord conn = clist.get(i);
1966 pw.print(" ");
1967 pw.print(conn.binding.intent.intent.getIntent()
1968 .toShortString(false, false, false, false));
1969 pw.print(" -> ");
1970 ProcessRecord proc = conn.binding.client;
1971 pw.println(proc != null ? proc.toShortString() : "null");
1972 }
1973 }
1974 }
1975 }
1976 if (dumpClient && r.app != null && r.app.thread != null) {
1977 pw.println(" Client:");
1978 pw.flush();
1979 try {
1980 TransferPipe tp = new TransferPipe();
1981 try {
1982 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
1983 r, args);
1984 tp.setBufferPrefix(" ");
1985 // Short timeout, since blocking here can
1986 // deadlock with the application.
1987 tp.go(fd, 2000);
1988 } finally {
1989 tp.kill();
1990 }
1991 } catch (IOException e) {
1992 pw.println(" Failure while dumping the service: " + e);
1993 } catch (RemoteException e) {
1994 pw.println(" Got a RemoteException while dumping the service");
1995 }
1996 needSep = true;
1997 }
1998 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07001999 needSep |= printed;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002000 }
2001 }
Amith Yamasani258848d2012-08-10 17:06:33 -07002002 } catch (Exception e) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002003 Log.w(TAG, "Exception in dumpServicesLocked", e);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002004 }
2005
2006 if (mPendingServices.size() > 0) {
2007 boolean printed = false;
2008 for (int i=0; i<mPendingServices.size(); i++) {
2009 ServiceRecord r = mPendingServices.get(i);
2010 if (!matcher.match(r, r.name)) {
2011 continue;
2012 }
2013 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
2014 continue;
2015 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002016 printedAnything = true;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002017 if (!printed) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002018 if (needSep) pw.println();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002019 needSep = true;
2020 pw.println(" Pending services:");
2021 printed = true;
2022 }
2023 pw.print(" * Pending "); pw.println(r);
2024 r.dump(pw, " ");
2025 }
2026 needSep = true;
2027 }
2028
2029 if (mRestartingServices.size() > 0) {
2030 boolean printed = false;
2031 for (int i=0; i<mRestartingServices.size(); i++) {
2032 ServiceRecord r = mRestartingServices.get(i);
2033 if (!matcher.match(r, r.name)) {
2034 continue;
2035 }
2036 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
2037 continue;
2038 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002039 printedAnything = true;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002040 if (!printed) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002041 if (needSep) pw.println();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002042 needSep = true;
2043 pw.println(" Restarting services:");
2044 printed = true;
2045 }
2046 pw.print(" * Restarting "); pw.println(r);
2047 r.dump(pw, " ");
2048 }
2049 needSep = true;
2050 }
2051
2052 if (mStoppingServices.size() > 0) {
2053 boolean printed = false;
2054 for (int i=0; i<mStoppingServices.size(); i++) {
2055 ServiceRecord r = mStoppingServices.get(i);
2056 if (!matcher.match(r, r.name)) {
2057 continue;
2058 }
2059 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
2060 continue;
2061 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002062 printedAnything = true;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002063 if (!printed) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002064 if (needSep) pw.println();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002065 needSep = true;
2066 pw.println(" Stopping services:");
2067 printed = true;
2068 }
2069 pw.print(" * Stopping "); pw.println(r);
2070 r.dump(pw, " ");
2071 }
2072 needSep = true;
2073 }
2074
2075 if (dumpAll) {
2076 if (mServiceConnections.size() > 0) {
2077 boolean printed = false;
2078 Iterator<ArrayList<ConnectionRecord>> it
2079 = mServiceConnections.values().iterator();
2080 while (it.hasNext()) {
2081 ArrayList<ConnectionRecord> r = it.next();
2082 for (int i=0; i<r.size(); i++) {
2083 ConnectionRecord cr = r.get(i);
2084 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
2085 continue;
2086 }
2087 if (dumpPackage != null && (cr.binding.client == null
2088 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
2089 continue;
2090 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002091 printedAnything = true;
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002092 if (!printed) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002093 if (needSep) pw.println();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002094 needSep = true;
2095 pw.println(" Connection bindings to services:");
2096 printed = true;
2097 }
2098 pw.print(" * "); pw.println(cr);
2099 cr.dump(pw, " ");
2100 }
2101 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002102 }
2103 }
2104
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002105 if (!printedAnything) {
2106 pw.println(" (nothing)");
2107 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002108 }
2109
2110 /**
2111 * There are three ways to call this:
2112 * - no service specified: dump all the services
2113 * - a flattened component name that matched an existing service was specified as the
2114 * first arg: dump that one service
2115 * - the first arg isn't the flattened component name of an existing service:
2116 * dump all services whose component contains the first arg as a substring
2117 */
2118 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
2119 int opti, boolean dumpAll) {
2120 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
2121
Dianne Hackborn1676c852012-09-10 14:52:30 -07002122 synchronized (this) {
2123 int[] users = mAm.getUsersLocked();
2124 if ("all".equals(name)) {
2125 for (int user : users) {
2126 for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
Amith Yamasani258848d2012-08-10 17:06:33 -07002127 services.add(r1);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002128 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002129 }
Dianne Hackborn1676c852012-09-10 14:52:30 -07002130 } else {
2131 ComponentName componentName = name != null
2132 ? ComponentName.unflattenFromString(name) : null;
2133 int objectId = 0;
2134 if (componentName == null) {
2135 // Not a '/' separated full component name; maybe an object ID?
2136 try {
2137 objectId = Integer.parseInt(name, 16);
2138 name = null;
2139 componentName = null;
2140 } catch (RuntimeException e) {
2141 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002142 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002143
Dianne Hackborn1676c852012-09-10 14:52:30 -07002144 for (int user : users) {
2145 for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
Amith Yamasani258848d2012-08-10 17:06:33 -07002146 if (componentName != null) {
2147 if (r1.name.equals(componentName)) {
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002148 services.add(r1);
2149 }
Amith Yamasani258848d2012-08-10 17:06:33 -07002150 } else if (name != null) {
2151 if (r1.name.flattenToString().contains(name)) {
2152 services.add(r1);
2153 }
2154 } else if (System.identityHashCode(r1) == objectId) {
2155 services.add(r1);
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002156 }
2157 }
Dianne Hackborn599db5c2012-08-03 19:28:48 -07002158 }
2159 }
2160 }
2161
2162 if (services.size() <= 0) {
2163 return false;
2164 }
2165
2166 boolean needSep = false;
2167 for (int i=0; i<services.size(); i++) {
2168 if (needSep) {
2169 pw.println();
2170 }
2171 needSep = true;
2172 dumpService("", fd, pw, services.get(i), args, dumpAll);
2173 }
2174 return true;
2175 }
2176
2177 /**
2178 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
2179 * there is a thread associated with the service.
2180 */
2181 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
2182 final ServiceRecord r, String[] args, boolean dumpAll) {
2183 String innerPrefix = prefix + " ";
2184 synchronized (this) {
2185 pw.print(prefix); pw.print("SERVICE ");
2186 pw.print(r.shortName); pw.print(" ");
2187 pw.print(Integer.toHexString(System.identityHashCode(r)));
2188 pw.print(" pid=");
2189 if (r.app != null) pw.println(r.app.pid);
2190 else pw.println("(not running)");
2191 if (dumpAll) {
2192 r.dump(pw, innerPrefix);
2193 }
2194 }
2195 if (r.app != null && r.app.thread != null) {
2196 pw.print(prefix); pw.println(" Client:");
2197 pw.flush();
2198 try {
2199 TransferPipe tp = new TransferPipe();
2200 try {
2201 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
2202 tp.setBufferPrefix(prefix + " ");
2203 tp.go(fd);
2204 } finally {
2205 tp.kill();
2206 }
2207 } catch (IOException e) {
2208 pw.println(prefix + " Failure while dumping the service: " + e);
2209 } catch (RemoteException e) {
2210 pw.println(prefix + " Got a RemoteException while dumping the service");
2211 }
2212 }
2213 }
2214
2215}