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 17 package com.android.server.am; 18 19 import com.android.internal.app.ProcessStats; 20 import com.android.internal.os.BatteryStatsImpl; 21 import com.android.server.LocalServices; 22 import com.android.server.notification.NotificationManagerInternal; 23 24 import android.app.INotificationManager; 25 import android.app.Notification; 26 import android.app.NotificationManager; 27 import android.app.PendingIntent; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.pm.ApplicationInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.ServiceInfo; 34 import android.net.Uri; 35 import android.os.Binder; 36 import android.os.IBinder; 37 import android.os.RemoteException; 38 import android.os.SystemClock; 39 import android.os.UserHandle; 40 import android.provider.Settings; 41 import android.util.ArrayMap; 42 import android.util.Slog; 43 import android.util.TimeUtils; 44 45 import java.io.PrintWriter; 46 import java.util.ArrayList; 47 import java.util.List; 48 import java.util.Objects; 49 50 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 51 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 52 53 /** 54 * A running application service. 55 */ 56 final 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 ProcessStats.ServiceState tracker; // tracking service execution, may be null 92 ProcessStats.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 StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent, ActivityManagerService.NeededUriGrants _neededGrants)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 getUriPermissionsLocked()142 UriPermissionOwner getUriPermissionsLocked() { 143 if (uriPermissions == null) { 144 uriPermissions = new UriPermissionOwner(sr.ams, this); 145 } 146 return uriPermissions; 147 } 148 removeUriPermissionsLocked()149 void removeUriPermissionsLocked() { 150 if (uriPermissions != null) { 151 uriPermissions.removeUriPermissionsLocked(); 152 uriPermissions = null; 153 } 154 } 155 toString()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 dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now)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 dump(PrintWriter pw, String prefix)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 ServiceRecord(ActivityManagerService ams, BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name, Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg, Runnable restarter)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 getTracker()329 public ProcessStats.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 forceClearTracker()342 public void forceClearTracker() { 343 if (tracker != null) { 344 tracker.clearCurrentOwner(this, true); 345 tracker = null; 346 } 347 } 348 makeRestarting(int memFactor, long now)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 retrieveAppBindingLocked(Intent intent, ProcessRecord app)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 hasAutoCreateConnections()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 resetRestartCounter()394 public void resetRestartCounter() { 395 restartCount = 0; 396 restartDelay = 0; 397 restartTime = 0; 398 } 399 findDeliveredStart(int id, boolean remove)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 getLastStartId()413 public int getLastStartId() { 414 return lastStartId; 415 } 416 makeNextStartId()417 public int makeNextStartId() { 418 lastStartId++; 419 if (lastStartId < 1) { 420 lastStartId = 1; 421 } 422 return lastStartId; 423 } 424 postNotification()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, true); 520 ams.crashApplication(appUid, appPid, localPackageName, 521 "Bad notification for startForeground: " + e); 522 } 523 } 524 }); 525 } 526 } 527 cancelNotification()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 stripForegroundServiceFlagFromNotification()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 clearDeliveredStartsLocked()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 toString()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