ServiceRecord.java revision 67324c990c4fbad238119a4667341d5618b2bea2
1/* 2 * Copyright (C) 2006 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 com.android.internal.app.procstats.ServiceState; 20import com.android.internal.os.BatteryStatsImpl; 21import com.android.server.LocalServices; 22import com.android.server.notification.NotificationManagerInternal; 23 24import android.app.INotificationManager; 25import android.app.Notification; 26import android.app.NotificationManager; 27import android.app.PendingIntent; 28import android.content.ComponentName; 29import android.content.Context; 30import android.content.Intent; 31import android.content.pm.ApplicationInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.ServiceInfo; 34import android.net.Uri; 35import android.os.Binder; 36import android.os.IBinder; 37import android.os.RemoteException; 38import android.os.SystemClock; 39import android.os.UserHandle; 40import android.provider.Settings; 41import android.util.ArrayMap; 42import android.util.Slog; 43import android.util.TimeUtils; 44 45import java.io.PrintWriter; 46import java.util.ArrayList; 47import java.util.List; 48import java.util.Objects; 49 50import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 51import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 52 53/** 54 * A running application service. 55 */ 56final class ServiceRecord extends Binder { 57 private static final String TAG = TAG_WITH_CLASS_NAME ? "ServiceRecord" : TAG_AM; 58 59 // Maximum number of delivery attempts before giving up. 60 static final int MAX_DELIVERY_COUNT = 3; 61 62 // Maximum number of times it can fail during execution before giving up. 63 static final int MAX_DONE_EXECUTING_COUNT = 6; 64 65 final ActivityManagerService ams; 66 final BatteryStatsImpl.Uid.Pkg.Serv stats; 67 final ComponentName name; // service component. 68 final String shortName; // name.flattenToShortString(). 69 final Intent.FilterComparison intent; 70 // original intent used to find service. 71 final ServiceInfo serviceInfo; 72 // all information about the service. 73 final ApplicationInfo appInfo; 74 // information about service's app. 75 final int userId; // user that this service is running as 76 final String packageName; // the package implementing intent's component 77 final String processName; // process where this component wants to run 78 final String permission;// permission needed to access service 79 final boolean exported; // from ServiceInfo.exported 80 final Runnable restarter; // used to schedule retries of starting the service 81 final long createTime; // when this service was created 82 final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings 83 = new ArrayMap<Intent.FilterComparison, IntentBindRecord>(); 84 // All active bindings to the service. 85 final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections 86 = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>(); 87 // IBinder -> ConnectionRecord of all bound clients 88 89 ProcessRecord app; // where this service is running or null. 90 ProcessRecord isolatedProc; // keep track of isolated process, if requested 91 ServiceState tracker; // tracking service execution, may be null 92 ServiceState restartTracker; // tracking service restart 93 boolean delayed; // are we waiting to start this service in the background? 94 boolean isForeground; // is service currently in foreground mode? 95 int foregroundId; // Notification ID of last foreground req. 96 Notification foregroundNoti; // Notification record of foreground state. 97 long lastActivity; // last time there was some activity on the service. 98 long startingBgTimeout; // time at which we scheduled this for a delayed start. 99 boolean startRequested; // someone explicitly called start? 100 boolean delayedStop; // service has been stopped but is in a delayed start? 101 boolean stopIfKilled; // last onStart() said to stop if service killed? 102 boolean callStart; // last onStart() has asked to alway be called on restart. 103 int executeNesting; // number of outstanding operations keeping foreground. 104 boolean executeFg; // should we be executing in the foreground? 105 long executingStart; // start time of last execute request. 106 boolean createdFromFg; // was this service last created due to a foreground process call? 107 int crashCount; // number of times proc has crashed with service running 108 int totalRestartCount; // number of times we have had to restart. 109 int restartCount; // number of restarts performed in a row. 110 long restartDelay; // delay until next restart attempt. 111 long restartTime; // time of last restart. 112 long nextRestartTime; // time when restartDelay will expire. 113 boolean destroying; // set when we have started destroying the service 114 long destroyTime; // time at which destory was initiated. 115 116 String stringName; // caching of toString 117 118 private int lastStartId; // identifier of most recent start request. 119 120 static class StartItem { 121 final ServiceRecord sr; 122 final boolean taskRemoved; 123 final int id; 124 final Intent intent; 125 final ActivityManagerService.NeededUriGrants neededGrants; 126 long deliveredTime; 127 int deliveryCount; 128 int doneExecutingCount; 129 UriPermissionOwner uriPermissions; 130 131 String stringName; // caching of toString 132 133 StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent, 134 ActivityManagerService.NeededUriGrants _neededGrants) { 135 sr = _sr; 136 taskRemoved = _taskRemoved; 137 id = _id; 138 intent = _intent; 139 neededGrants = _neededGrants; 140 } 141 142 UriPermissionOwner getUriPermissionsLocked() { 143 if (uriPermissions == null) { 144 uriPermissions = new UriPermissionOwner(sr.ams, this); 145 } 146 return uriPermissions; 147 } 148 149 void removeUriPermissionsLocked() { 150 if (uriPermissions != null) { 151 uriPermissions.removeUriPermissionsLocked(); 152 uriPermissions = null; 153 } 154 } 155 156 public String toString() { 157 if (stringName != null) { 158 return stringName; 159 } 160 StringBuilder sb = new StringBuilder(128); 161 sb.append("ServiceRecord{") 162 .append(Integer.toHexString(System.identityHashCode(sr))) 163 .append(' ').append(sr.shortName) 164 .append(" StartItem ") 165 .append(Integer.toHexString(System.identityHashCode(this))) 166 .append(" id=").append(id).append('}'); 167 return stringName = sb.toString(); 168 } 169 } 170 171 final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>(); 172 // start() arguments which been delivered. 173 final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>(); 174 // start() arguments that haven't yet been delivered. 175 176 void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) { 177 final int N = list.size(); 178 for (int i=0; i<N; i++) { 179 StartItem si = list.get(i); 180 pw.print(prefix); pw.print("#"); pw.print(i); 181 pw.print(" id="); pw.print(si.id); 182 if (now != 0) { 183 pw.print(" dur="); 184 TimeUtils.formatDuration(si.deliveredTime, now, pw); 185 } 186 if (si.deliveryCount != 0) { 187 pw.print(" dc="); pw.print(si.deliveryCount); 188 } 189 if (si.doneExecutingCount != 0) { 190 pw.print(" dxc="); pw.print(si.doneExecutingCount); 191 } 192 pw.println(""); 193 pw.print(prefix); pw.print(" intent="); 194 if (si.intent != null) pw.println(si.intent.toString()); 195 else pw.println("null"); 196 if (si.neededGrants != null) { 197 pw.print(prefix); pw.print(" neededGrants="); 198 pw.println(si.neededGrants); 199 } 200 if (si.uriPermissions != null) { 201 si.uriPermissions.dump(pw, prefix); 202 } 203 } 204 } 205 206 void dump(PrintWriter pw, String prefix) { 207 pw.print(prefix); pw.print("intent={"); 208 pw.print(intent.getIntent().toShortString(false, true, false, true)); 209 pw.println('}'); 210 pw.print(prefix); pw.print("packageName="); pw.println(packageName); 211 pw.print(prefix); pw.print("processName="); pw.println(processName); 212 if (permission != null) { 213 pw.print(prefix); pw.print("permission="); pw.println(permission); 214 } 215 long now = SystemClock.uptimeMillis(); 216 long nowReal = SystemClock.elapsedRealtime(); 217 if (appInfo != null) { 218 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir); 219 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) { 220 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir); 221 } 222 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir); 223 } 224 pw.print(prefix); pw.print("app="); pw.println(app); 225 if (isolatedProc != null) { 226 pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc); 227 } 228 if (delayed) { 229 pw.print(prefix); pw.print("delayed="); pw.println(delayed); 230 } 231 if (isForeground || foregroundId != 0) { 232 pw.print(prefix); pw.print("isForeground="); pw.print(isForeground); 233 pw.print(" foregroundId="); pw.print(foregroundId); 234 pw.print(" foregroundNoti="); pw.println(foregroundNoti); 235 } 236 pw.print(prefix); pw.print("createTime="); 237 TimeUtils.formatDuration(createTime, nowReal, pw); 238 pw.print(" startingBgTimeout="); 239 TimeUtils.formatDuration(startingBgTimeout, now, pw); 240 pw.println(); 241 pw.print(prefix); pw.print("lastActivity="); 242 TimeUtils.formatDuration(lastActivity, now, pw); 243 pw.print(" restartTime="); 244 TimeUtils.formatDuration(restartTime, now, pw); 245 pw.print(" createdFromFg="); pw.println(createdFromFg); 246 if (startRequested || delayedStop || lastStartId != 0) { 247 pw.print(prefix); pw.print("startRequested="); pw.print(startRequested); 248 pw.print(" delayedStop="); pw.print(delayedStop); 249 pw.print(" stopIfKilled="); pw.print(stopIfKilled); 250 pw.print(" callStart="); pw.print(callStart); 251 pw.print(" lastStartId="); pw.println(lastStartId); 252 } 253 if (executeNesting != 0) { 254 pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting); 255 pw.print(" executeFg="); pw.print(executeFg); 256 pw.print(" executingStart="); 257 TimeUtils.formatDuration(executingStart, now, pw); 258 pw.println(); 259 } 260 if (destroying || destroyTime != 0) { 261 pw.print(prefix); pw.print("destroying="); pw.print(destroying); 262 pw.print(" destroyTime="); 263 TimeUtils.formatDuration(destroyTime, now, pw); 264 pw.println(); 265 } 266 if (crashCount != 0 || restartCount != 0 267 || restartDelay != 0 || nextRestartTime != 0) { 268 pw.print(prefix); pw.print("restartCount="); pw.print(restartCount); 269 pw.print(" restartDelay="); 270 TimeUtils.formatDuration(restartDelay, now, pw); 271 pw.print(" nextRestartTime="); 272 TimeUtils.formatDuration(nextRestartTime, now, pw); 273 pw.print(" crashCount="); pw.println(crashCount); 274 } 275 if (deliveredStarts.size() > 0) { 276 pw.print(prefix); pw.println("Delivered Starts:"); 277 dumpStartList(pw, prefix, deliveredStarts, now); 278 } 279 if (pendingStarts.size() > 0) { 280 pw.print(prefix); pw.println("Pending Starts:"); 281 dumpStartList(pw, prefix, pendingStarts, 0); 282 } 283 if (bindings.size() > 0) { 284 pw.print(prefix); pw.println("Bindings:"); 285 for (int i=0; i<bindings.size(); i++) { 286 IntentBindRecord b = bindings.valueAt(i); 287 pw.print(prefix); pw.print("* IntentBindRecord{"); 288 pw.print(Integer.toHexString(System.identityHashCode(b))); 289 if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) { 290 pw.append(" CREATE"); 291 } 292 pw.println("}:"); 293 b.dumpInService(pw, prefix + " "); 294 } 295 } 296 if (connections.size() > 0) { 297 pw.print(prefix); pw.println("All Connections:"); 298 for (int conni=0; conni<connections.size(); conni++) { 299 ArrayList<ConnectionRecord> c = connections.valueAt(conni); 300 for (int i=0; i<c.size(); i++) { 301 pw.print(prefix); pw.print(" "); pw.println(c.get(i)); 302 } 303 } 304 } 305 } 306 307 ServiceRecord(ActivityManagerService ams, 308 BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name, 309 Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg, 310 Runnable restarter) { 311 this.ams = ams; 312 this.stats = servStats; 313 this.name = name; 314 shortName = name.flattenToShortString(); 315 this.intent = intent; 316 serviceInfo = sInfo; 317 appInfo = sInfo.applicationInfo; 318 packageName = sInfo.applicationInfo.packageName; 319 processName = sInfo.processName; 320 permission = sInfo.permission; 321 exported = sInfo.exported; 322 this.restarter = restarter; 323 createTime = SystemClock.elapsedRealtime(); 324 lastActivity = SystemClock.uptimeMillis(); 325 userId = UserHandle.getUserId(appInfo.uid); 326 createdFromFg = callerIsFg; 327 } 328 329 public ServiceState getTracker() { 330 if (tracker != null) { 331 return tracker; 332 } 333 if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { 334 tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, 335 serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode, 336 serviceInfo.processName, serviceInfo.name); 337 tracker.applyNewOwner(this); 338 } 339 return tracker; 340 } 341 342 public void forceClearTracker() { 343 if (tracker != null) { 344 tracker.clearCurrentOwner(this, true); 345 tracker = null; 346 } 347 } 348 349 public void makeRestarting(int memFactor, long now) { 350 if (restartTracker == null) { 351 if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { 352 restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, 353 serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode, 354 serviceInfo.processName, serviceInfo.name); 355 } 356 if (restartTracker == null) { 357 return; 358 } 359 } 360 restartTracker.setRestarting(true, memFactor, now); 361 } 362 363 public AppBindRecord retrieveAppBindingLocked(Intent intent, 364 ProcessRecord app) { 365 Intent.FilterComparison filter = new Intent.FilterComparison(intent); 366 IntentBindRecord i = bindings.get(filter); 367 if (i == null) { 368 i = new IntentBindRecord(this, filter); 369 bindings.put(filter, i); 370 } 371 AppBindRecord a = i.apps.get(app); 372 if (a != null) { 373 return a; 374 } 375 a = new AppBindRecord(this, i, app); 376 i.apps.put(app, a); 377 return a; 378 } 379 380 public boolean hasAutoCreateConnections() { 381 // XXX should probably keep a count of the number of auto-create 382 // connections directly in the service. 383 for (int conni=connections.size()-1; conni>=0; conni--) { 384 ArrayList<ConnectionRecord> cr = connections.valueAt(conni); 385 for (int i=0; i<cr.size(); i++) { 386 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) { 387 return true; 388 } 389 } 390 } 391 return false; 392 } 393 394 public void resetRestartCounter() { 395 restartCount = 0; 396 restartDelay = 0; 397 restartTime = 0; 398 } 399 400 public StartItem findDeliveredStart(int id, boolean remove) { 401 final int N = deliveredStarts.size(); 402 for (int i=0; i<N; i++) { 403 StartItem si = deliveredStarts.get(i); 404 if (si.id == id) { 405 if (remove) deliveredStarts.remove(i); 406 return si; 407 } 408 } 409 410 return null; 411 } 412 413 public int getLastStartId() { 414 return lastStartId; 415 } 416 417 public int makeNextStartId() { 418 lastStartId++; 419 if (lastStartId < 1) { 420 lastStartId = 1; 421 } 422 return lastStartId; 423 } 424 425 public void postNotification() { 426 final int appUid = appInfo.uid; 427 final int appPid = app.pid; 428 if (foregroundId != 0 && foregroundNoti != null) { 429 // Do asynchronous communication with notification manager to 430 // avoid deadlocks. 431 final String localPackageName = packageName; 432 final int localForegroundId = foregroundId; 433 final Notification _foregroundNoti = foregroundNoti; 434 ams.mHandler.post(new Runnable() { 435 public void run() { 436 NotificationManagerInternal nm = LocalServices.getService( 437 NotificationManagerInternal.class); 438 if (nm == null) { 439 return; 440 } 441 Notification localForegroundNoti = _foregroundNoti; 442 try { 443 if (localForegroundNoti.getSmallIcon() == null) { 444 // It is not correct for the caller to supply a notification 445 // icon, but this used to be able to slip through, so for 446 // those dirty apps we will create a notification clearly 447 // blaming the app. 448 Slog.v(TAG, "Attempted to start a foreground service (" 449 + name 450 + ") with a broken notification (no icon: " 451 + localForegroundNoti 452 + ")"); 453 454 CharSequence appName = appInfo.loadLabel( 455 ams.mContext.getPackageManager()); 456 if (appName == null) { 457 appName = appInfo.packageName; 458 } 459 Context ctx = null; 460 try { 461 ctx = ams.mContext.createPackageContext( 462 appInfo.packageName, 0); 463 464 Notification.Builder notiBuilder = new Notification.Builder(ctx); 465 466 // it's ugly, but it clearly identifies the app 467 notiBuilder.setSmallIcon(appInfo.icon); 468 469 // mark as foreground 470 notiBuilder.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true); 471 472 // we are doing the app a kindness here 473 notiBuilder.setPriority(Notification.PRIORITY_MIN); 474 475 Intent runningIntent = new Intent( 476 Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 477 runningIntent.setData(Uri.fromParts("package", 478 appInfo.packageName, null)); 479 PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0, 480 runningIntent, PendingIntent.FLAG_UPDATE_CURRENT); 481 notiBuilder.setColor(ams.mContext.getColor( 482 com.android.internal 483 .R.color.system_notification_accent_color)); 484 notiBuilder.setContentTitle( 485 ams.mContext.getString( 486 com.android.internal.R.string 487 .app_running_notification_title, 488 appName)); 489 notiBuilder.setContentText( 490 ams.mContext.getString( 491 com.android.internal.R.string 492 .app_running_notification_text, 493 appName)); 494 notiBuilder.setContentIntent(pi); 495 496 localForegroundNoti = notiBuilder.build(); 497 } catch (PackageManager.NameNotFoundException e) { 498 } 499 } 500 if (localForegroundNoti.getSmallIcon() == null) { 501 // Notifications whose icon is 0 are defined to not show 502 // a notification, silently ignoring it. We don't want to 503 // just ignore it, we want to prevent the service from 504 // being foreground. 505 throw new RuntimeException("invalid service notification: " 506 + foregroundNoti); 507 } 508 int[] outId = new int[1]; 509 nm.enqueueNotification(localPackageName, localPackageName, 510 appUid, appPid, null, localForegroundId, localForegroundNoti, 511 outId, userId); 512 513 foregroundNoti = localForegroundNoti; // save it for amending next time 514 } catch (RuntimeException e) { 515 Slog.w(TAG, "Error showing notification for service", e); 516 // If it gave us a garbage notification, it doesn't 517 // get to be foreground. 518 ams.setServiceForeground(name, ServiceRecord.this, 519 0, null, 0); 520 ams.crashApplication(appUid, appPid, localPackageName, 521 "Bad notification for startForeground: " + e); 522 } 523 } 524 }); 525 } 526 } 527 528 public void cancelNotification() { 529 if (foregroundId != 0) { 530 // Do asynchronous communication with notification manager to 531 // avoid deadlocks. 532 final String localPackageName = packageName; 533 final int localForegroundId = foregroundId; 534 ams.mHandler.post(new Runnable() { 535 public void run() { 536 INotificationManager inm = NotificationManager.getService(); 537 if (inm == null) { 538 return; 539 } 540 try { 541 inm.cancelNotificationWithTag(localPackageName, null, 542 localForegroundId, userId); 543 } catch (RuntimeException e) { 544 Slog.w(TAG, "Error canceling notification for service", e); 545 } catch (RemoteException e) { 546 } 547 } 548 }); 549 } 550 } 551 552 public void stripForegroundServiceFlagFromNotification() { 553 if (foregroundId == 0) { 554 return; 555 } 556 557 final int localForegroundId = foregroundId; 558 final int localUserId = userId; 559 final String localPackageName = packageName; 560 561 // Do asynchronous communication with notification manager to 562 // avoid deadlocks. 563 ams.mHandler.post(new Runnable() { 564 @Override 565 public void run() { 566 NotificationManagerInternal nmi = LocalServices.getService( 567 NotificationManagerInternal.class); 568 if (nmi == null) { 569 return; 570 } 571 nmi.removeForegroundServiceFlagFromNotification(localPackageName, localForegroundId, 572 localUserId); 573 } 574 }); 575 } 576 577 public void clearDeliveredStartsLocked() { 578 for (int i=deliveredStarts.size()-1; i>=0; i--) { 579 deliveredStarts.get(i).removeUriPermissionsLocked(); 580 } 581 deliveredStarts.clear(); 582 } 583 584 public String toString() { 585 if (stringName != null) { 586 return stringName; 587 } 588 StringBuilder sb = new StringBuilder(128); 589 sb.append("ServiceRecord{") 590 .append(Integer.toHexString(System.identityHashCode(this))) 591 .append(" u").append(userId) 592 .append(' ').append(shortName).append('}'); 593 return stringName = sb.toString(); 594 } 595} 596