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