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