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