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.NotificationManagerService; 22 23 import android.app.INotificationManager; 24 import android.app.Notification; 25 import android.app.NotificationManager; 26 import android.app.PendingIntent; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.ApplicationInfo; 31 import android.content.pm.PackageManager; 32 import android.content.pm.ServiceInfo; 33 import android.net.Uri; 34 import android.os.Binder; 35 import android.os.IBinder; 36 import android.os.RemoteException; 37 import android.os.SystemClock; 38 import android.os.UserHandle; 39 import android.provider.Settings; 40 import android.util.ArrayMap; 41 import android.util.Slog; 42 import android.util.TimeUtils; 43 44 import java.io.PrintWriter; 45 import java.util.ArrayList; 46 import java.util.List; 47 48 /** 49 * A running application service. 50 */ 51 final 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 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 109 String stringName; // caching of toString 110 111 private int lastStartId; // identifier of most recent start request. 112 113 static class StartItem { 114 final ServiceRecord sr; 115 final boolean taskRemoved; 116 final int id; 117 final Intent intent; 118 final ActivityManagerService.NeededUriGrants neededGrants; 119 long deliveredTime; 120 int deliveryCount; 121 int doneExecutingCount; 122 UriPermissionOwner uriPermissions; 123 124 String stringName; // caching of toString 125 126 StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent, 127 ActivityManagerService.NeededUriGrants _neededGrants) { 128 sr = _sr; 129 taskRemoved = _taskRemoved; 130 id = _id; 131 intent = _intent; 132 neededGrants = _neededGrants; 133 } 134 135 UriPermissionOwner getUriPermissionsLocked() { 136 if (uriPermissions == null) { 137 uriPermissions = new UriPermissionOwner(sr.ams, this); 138 } 139 return uriPermissions; 140 } 141 142 void removeUriPermissionsLocked() { 143 if (uriPermissions != null) { 144 uriPermissions.removeUriPermissionsLocked(); 145 uriPermissions = null; 146 } 147 } 148 149 public String toString() { 150 if (stringName != null) { 151 return stringName; 152 } 153 StringBuilder sb = new StringBuilder(128); 154 sb.append("ServiceRecord{") 155 .append(Integer.toHexString(System.identityHashCode(sr))) 156 .append(' ').append(sr.shortName) 157 .append(" StartItem ") 158 .append(Integer.toHexString(System.identityHashCode(this))) 159 .append(" id=").append(id).append('}'); 160 return stringName = sb.toString(); 161 } 162 } 163 164 final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>(); 165 // start() arguments which been delivered. 166 final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>(); 167 // start() arguments that haven't yet been delivered. 168 169 void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) { 170 final int N = list.size(); 171 for (int i=0; i<N; i++) { 172 StartItem si = list.get(i); 173 pw.print(prefix); pw.print("#"); pw.print(i); 174 pw.print(" id="); pw.print(si.id); 175 if (now != 0) { 176 pw.print(" dur="); 177 TimeUtils.formatDuration(si.deliveredTime, now, pw); 178 } 179 if (si.deliveryCount != 0) { 180 pw.print(" dc="); pw.print(si.deliveryCount); 181 } 182 if (si.doneExecutingCount != 0) { 183 pw.print(" dxc="); pw.print(si.doneExecutingCount); 184 } 185 pw.println(""); 186 pw.print(prefix); pw.print(" intent="); 187 if (si.intent != null) pw.println(si.intent.toString()); 188 else pw.println("null"); 189 if (si.neededGrants != null) { 190 pw.print(prefix); pw.print(" neededGrants="); 191 pw.println(si.neededGrants); 192 } 193 if (si.uriPermissions != null) { 194 if (si.uriPermissions.readUriPermissions != null) { 195 pw.print(prefix); pw.print(" readUriPermissions="); 196 pw.println(si.uriPermissions.readUriPermissions); 197 } 198 if (si.uriPermissions.writeUriPermissions != null) { 199 pw.print(prefix); pw.print(" writeUriPermissions="); 200 pw.println(si.uriPermissions.writeUriPermissions); 201 } 202 } 203 } 204 } 205 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 pw.print(prefix); pw.print("baseDir="); pw.println(baseDir); 218 if (!resDir.equals(baseDir)) { 219 pw.print(prefix); pw.print("resDir="); pw.println(resDir); 220 } 221 pw.print(prefix); pw.print("dataDir="); pw.println(dataDir); 222 pw.print(prefix); pw.print("app="); pw.println(app); 223 if (isolatedProc != null) { 224 pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc); 225 } 226 if (delayed) { 227 pw.print(prefix); pw.print("delayed="); pw.println(delayed); 228 } 229 if (isForeground || foregroundId != 0) { 230 pw.print(prefix); pw.print("isForeground="); pw.print(isForeground); 231 pw.print(" foregroundId="); pw.print(foregroundId); 232 pw.print(" foregroundNoti="); pw.println(foregroundNoti); 233 } 234 pw.print(prefix); pw.print("createTime="); 235 TimeUtils.formatDuration(createTime, nowReal, pw); 236 pw.print(" startingBgTimeout="); 237 TimeUtils.formatDuration(startingBgTimeout, now, pw); 238 pw.println(); 239 pw.print(prefix); pw.print("lastActivity="); 240 TimeUtils.formatDuration(lastActivity, now, pw); 241 pw.print(" restartTime="); 242 TimeUtils.formatDuration(restartTime, now, pw); 243 pw.print(" createdFromFg="); pw.println(createdFromFg); 244 if (startRequested || delayedStop || lastStartId != 0) { 245 pw.print(prefix); pw.print("startRequested="); pw.print(startRequested); 246 pw.print(" delayedStop="); pw.print(delayedStop); 247 pw.print(" stopIfKilled="); pw.print(stopIfKilled); 248 pw.print(" callStart="); pw.print(callStart); 249 pw.print(" lastStartId="); pw.println(lastStartId); 250 } 251 if (executeNesting != 0) { 252 pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting); 253 pw.print(" executeFg="); pw.print(executeFg); 254 pw.print(" executingStart="); 255 TimeUtils.formatDuration(executingStart, now, pw); 256 pw.println(); 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 baseDir = sInfo.applicationInfo.sourceDir; 314 resDir = sInfo.applicationInfo.publicSourceDir; 315 dataDir = sInfo.applicationInfo.dataDir; 316 exported = sInfo.exported; 317 this.restarter = restarter; 318 createTime = SystemClock.elapsedRealtime(); 319 lastActivity = SystemClock.uptimeMillis(); 320 userId = UserHandle.getUserId(appInfo.uid); 321 createdFromFg = callerIsFg; 322 } 323 324 public ProcessStats.ServiceState getTracker() { 325 if (tracker != null) { 326 return tracker; 327 } 328 if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { 329 tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, 330 serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name); 331 tracker.applyNewOwner(this); 332 } 333 return tracker; 334 } 335 336 public void forceClearTracker() { 337 if (tracker != null) { 338 tracker.clearCurrentOwner(this, true); 339 tracker = null; 340 } 341 } 342 343 public AppBindRecord retrieveAppBindingLocked(Intent intent, 344 ProcessRecord app) { 345 Intent.FilterComparison filter = new Intent.FilterComparison(intent); 346 IntentBindRecord i = bindings.get(filter); 347 if (i == null) { 348 i = new IntentBindRecord(this, filter); 349 bindings.put(filter, i); 350 } 351 AppBindRecord a = i.apps.get(app); 352 if (a != null) { 353 return a; 354 } 355 a = new AppBindRecord(this, i, app); 356 i.apps.put(app, a); 357 return a; 358 } 359 360 public boolean hasAutoCreateConnections() { 361 // XXX should probably keep a count of the number of auto-create 362 // connections directly in the service. 363 for (int conni=connections.size()-1; conni>=0; conni--) { 364 ArrayList<ConnectionRecord> cr = connections.valueAt(conni); 365 for (int i=0; i<cr.size(); i++) { 366 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) { 367 return true; 368 } 369 } 370 } 371 return false; 372 } 373 374 public void resetRestartCounter() { 375 restartCount = 0; 376 restartDelay = 0; 377 restartTime = 0; 378 } 379 380 public StartItem findDeliveredStart(int id, boolean remove) { 381 final int N = deliveredStarts.size(); 382 for (int i=0; i<N; i++) { 383 StartItem si = deliveredStarts.get(i); 384 if (si.id == id) { 385 if (remove) deliveredStarts.remove(i); 386 return si; 387 } 388 } 389 390 return null; 391 } 392 393 public int getLastStartId() { 394 return lastStartId; 395 } 396 397 public int makeNextStartId() { 398 lastStartId++; 399 if (lastStartId < 1) { 400 lastStartId = 1; 401 } 402 return lastStartId; 403 } 404 405 public void postNotification() { 406 final int appUid = appInfo.uid; 407 final int appPid = app.pid; 408 if (foregroundId != 0 && foregroundNoti != null) { 409 // Do asynchronous communication with notification manager to 410 // avoid deadlocks. 411 final String localPackageName = packageName; 412 final int localForegroundId = foregroundId; 413 final Notification localForegroundNoti = foregroundNoti; 414 ams.mHandler.post(new Runnable() { 415 public void run() { 416 NotificationManagerService nm = 417 (NotificationManagerService) NotificationManager.getService(); 418 if (nm == null) { 419 return; 420 } 421 try { 422 if (localForegroundNoti.icon == 0) { 423 // It is not correct for the caller to supply a notification 424 // icon, but this used to be able to slip through, so for 425 // those dirty apps give it the app's icon. 426 localForegroundNoti.icon = appInfo.icon; 427 428 // Do not allow apps to present a sneaky invisible content view either. 429 localForegroundNoti.contentView = null; 430 localForegroundNoti.bigContentView = null; 431 CharSequence appName = appInfo.loadLabel( 432 ams.mContext.getPackageManager()); 433 if (appName == null) { 434 appName = appInfo.packageName; 435 } 436 Context ctx = null; 437 try { 438 ctx = ams.mContext.createPackageContext( 439 appInfo.packageName, 0); 440 Intent runningIntent = new Intent( 441 Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 442 runningIntent.setData(Uri.fromParts("package", 443 appInfo.packageName, null)); 444 PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0, 445 runningIntent, PendingIntent.FLAG_UPDATE_CURRENT); 446 localForegroundNoti.setLatestEventInfo(ctx, 447 ams.mContext.getString( 448 com.android.internal.R.string 449 .app_running_notification_title, 450 appName), 451 ams.mContext.getString( 452 com.android.internal.R.string 453 .app_running_notification_text, 454 appName), 455 pi); 456 } catch (PackageManager.NameNotFoundException e) { 457 localForegroundNoti.icon = 0; 458 } 459 } 460 if (localForegroundNoti.icon == 0) { 461 // Notifications whose icon is 0 are defined to not show 462 // a notification, silently ignoring it. We don't want to 463 // just ignore it, we want to prevent the service from 464 // being foreground. 465 throw new RuntimeException("icon must be non-zero"); 466 } 467 int[] outId = new int[1]; 468 nm.enqueueNotificationInternal(localPackageName, localPackageName, 469 appUid, appPid, null, localForegroundId, localForegroundNoti, 470 outId, userId); 471 } catch (RuntimeException e) { 472 Slog.w(ActivityManagerService.TAG, 473 "Error showing notification for service", e); 474 // If it gave us a garbage notification, it doesn't 475 // get to be foreground. 476 ams.setServiceForeground(name, ServiceRecord.this, 477 0, null, true); 478 ams.crashApplication(appUid, appPid, localPackageName, 479 "Bad notification for startForeground: " + e); 480 } 481 } 482 }); 483 } 484 } 485 486 public void cancelNotification() { 487 if (foregroundId != 0) { 488 // Do asynchronous communication with notification manager to 489 // avoid deadlocks. 490 final String localPackageName = packageName; 491 final int localForegroundId = foregroundId; 492 ams.mHandler.post(new Runnable() { 493 public void run() { 494 INotificationManager inm = NotificationManager.getService(); 495 if (inm == null) { 496 return; 497 } 498 try { 499 inm.cancelNotificationWithTag(localPackageName, null, 500 localForegroundId, userId); 501 } catch (RuntimeException e) { 502 Slog.w(ActivityManagerService.TAG, 503 "Error canceling notification for service", e); 504 } catch (RemoteException e) { 505 } 506 } 507 }); 508 } 509 } 510 511 public void clearDeliveredStartsLocked() { 512 for (int i=deliveredStarts.size()-1; i>=0; i--) { 513 deliveredStarts.get(i).removeUriPermissionsLocked(); 514 } 515 deliveredStarts.clear(); 516 } 517 518 public String toString() { 519 if (stringName != null) { 520 return stringName; 521 } 522 StringBuilder sb = new StringBuilder(128); 523 sb.append("ServiceRecord{") 524 .append(Integer.toHexString(System.identityHashCode(this))) 525 .append(" u").append(userId) 526 .append(' ').append(shortName).append('}'); 527 return stringName = sb.toString(); 528 } 529 } 530