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