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.LocalServices; 22 import com.android.server.notification.NotificationManagerInternal; 23 24 import android.app.INotificationManager; 25 import android.app.Notification; 26 import android.app.NotificationManager; 27 import android.app.PendingIntent; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.pm.ApplicationInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.ServiceInfo; 34 import android.net.Uri; 35 import android.os.Binder; 36 import android.os.IBinder; 37 import android.os.RemoteException; 38 import android.os.SystemClock; 39 import android.os.UserHandle; 40 import android.provider.Settings; 41 import android.util.ArrayMap; 42 import android.util.Slog; 43 import android.util.TimeUtils; 44 45 import java.io.PrintWriter; 46 import java.util.ArrayList; 47 import java.util.List; 48 import java.util.Objects; 49 50 /** 51 * A running application service. 52 */ 53 final 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 boolean destroying; // set when we have started destroying the service 109 long destroyTime; // time at which destory was initiated. 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 StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent, ActivityManagerService.NeededUriGrants _neededGrants)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 getUriPermissionsLocked()137 UriPermissionOwner getUriPermissionsLocked() { 138 if (uriPermissions == null) { 139 uriPermissions = new UriPermissionOwner(sr.ams, this); 140 } 141 return uriPermissions; 142 } 143 removeUriPermissionsLocked()144 void removeUriPermissionsLocked() { 145 if (uriPermissions != null) { 146 uriPermissions.removeUriPermissionsLocked(); 147 uriPermissions = null; 148 } 149 } 150 toString()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 dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now)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 si.uriPermissions.dump(pw, prefix); 197 } 198 } 199 } 200 dump(PrintWriter pw, String prefix)201 void dump(PrintWriter pw, String prefix) { 202 pw.print(prefix); pw.print("intent={"); 203 pw.print(intent.getIntent().toShortString(false, true, false, true)); 204 pw.println('}'); 205 pw.print(prefix); pw.print("packageName="); pw.println(packageName); 206 pw.print(prefix); pw.print("processName="); pw.println(processName); 207 if (permission != null) { 208 pw.print(prefix); pw.print("permission="); pw.println(permission); 209 } 210 long now = SystemClock.uptimeMillis(); 211 long nowReal = SystemClock.elapsedRealtime(); 212 if (appInfo != null) { 213 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir); 214 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) { 215 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir); 216 } 217 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir); 218 } 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 (delayed) { 224 pw.print(prefix); pw.print("delayed="); pw.println(delayed); 225 } 226 if (isForeground || foregroundId != 0) { 227 pw.print(prefix); pw.print("isForeground="); pw.print(isForeground); 228 pw.print(" foregroundId="); pw.print(foregroundId); 229 pw.print(" foregroundNoti="); pw.println(foregroundNoti); 230 } 231 pw.print(prefix); pw.print("createTime="); 232 TimeUtils.formatDuration(createTime, nowReal, pw); 233 pw.print(" startingBgTimeout="); 234 TimeUtils.formatDuration(startingBgTimeout, now, pw); 235 pw.println(); 236 pw.print(prefix); pw.print("lastActivity="); 237 TimeUtils.formatDuration(lastActivity, now, pw); 238 pw.print(" restartTime="); 239 TimeUtils.formatDuration(restartTime, now, pw); 240 pw.print(" createdFromFg="); pw.println(createdFromFg); 241 if (startRequested || delayedStop || lastStartId != 0) { 242 pw.print(prefix); pw.print("startRequested="); pw.print(startRequested); 243 pw.print(" delayedStop="); pw.print(delayedStop); 244 pw.print(" stopIfKilled="); pw.print(stopIfKilled); 245 pw.print(" callStart="); pw.print(callStart); 246 pw.print(" lastStartId="); pw.println(lastStartId); 247 } 248 if (executeNesting != 0) { 249 pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting); 250 pw.print(" executeFg="); pw.print(executeFg); 251 pw.print(" executingStart="); 252 TimeUtils.formatDuration(executingStart, now, pw); 253 pw.println(); 254 } 255 if (destroying || destroyTime != 0) { 256 pw.print(prefix); pw.print("destroying="); pw.print(destroying); 257 pw.print(" destroyTime="); 258 TimeUtils.formatDuration(destroyTime, now, pw); 259 pw.println(); 260 } 261 if (crashCount != 0 || restartCount != 0 262 || restartDelay != 0 || nextRestartTime != 0) { 263 pw.print(prefix); pw.print("restartCount="); pw.print(restartCount); 264 pw.print(" restartDelay="); 265 TimeUtils.formatDuration(restartDelay, now, pw); 266 pw.print(" nextRestartTime="); 267 TimeUtils.formatDuration(nextRestartTime, now, pw); 268 pw.print(" crashCount="); pw.println(crashCount); 269 } 270 if (deliveredStarts.size() > 0) { 271 pw.print(prefix); pw.println("Delivered Starts:"); 272 dumpStartList(pw, prefix, deliveredStarts, now); 273 } 274 if (pendingStarts.size() > 0) { 275 pw.print(prefix); pw.println("Pending Starts:"); 276 dumpStartList(pw, prefix, pendingStarts, 0); 277 } 278 if (bindings.size() > 0) { 279 pw.print(prefix); pw.println("Bindings:"); 280 for (int i=0; i<bindings.size(); i++) { 281 IntentBindRecord b = bindings.valueAt(i); 282 pw.print(prefix); pw.print("* IntentBindRecord{"); 283 pw.print(Integer.toHexString(System.identityHashCode(b))); 284 if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) { 285 pw.append(" CREATE"); 286 } 287 pw.println("}:"); 288 b.dumpInService(pw, prefix + " "); 289 } 290 } 291 if (connections.size() > 0) { 292 pw.print(prefix); pw.println("All Connections:"); 293 for (int conni=0; conni<connections.size(); conni++) { 294 ArrayList<ConnectionRecord> c = connections.valueAt(conni); 295 for (int i=0; i<c.size(); i++) { 296 pw.print(prefix); pw.print(" "); pw.println(c.get(i)); 297 } 298 } 299 } 300 } 301 ServiceRecord(ActivityManagerService ams, BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name, Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg, Runnable restarter)302 ServiceRecord(ActivityManagerService ams, 303 BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name, 304 Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg, 305 Runnable restarter) { 306 this.ams = ams; 307 this.stats = servStats; 308 this.name = name; 309 shortName = name.flattenToShortString(); 310 this.intent = intent; 311 serviceInfo = sInfo; 312 appInfo = sInfo.applicationInfo; 313 packageName = sInfo.applicationInfo.packageName; 314 processName = sInfo.processName; 315 permission = sInfo.permission; 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 getTracker()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.applicationInfo.versionCode, 331 serviceInfo.processName, serviceInfo.name); 332 tracker.applyNewOwner(this); 333 } 334 return tracker; 335 } 336 forceClearTracker()337 public void forceClearTracker() { 338 if (tracker != null) { 339 tracker.clearCurrentOwner(this, true); 340 tracker = null; 341 } 342 } 343 makeRestarting(int memFactor, long now)344 public void makeRestarting(int memFactor, long now) { 345 if (restartTracker == null) { 346 if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { 347 restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, 348 serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode, 349 serviceInfo.processName, serviceInfo.name); 350 } 351 if (restartTracker == null) { 352 return; 353 } 354 } 355 restartTracker.setRestarting(true, memFactor, now); 356 } 357 retrieveAppBindingLocked(Intent intent, ProcessRecord app)358 public AppBindRecord retrieveAppBindingLocked(Intent intent, 359 ProcessRecord app) { 360 Intent.FilterComparison filter = new Intent.FilterComparison(intent); 361 IntentBindRecord i = bindings.get(filter); 362 if (i == null) { 363 i = new IntentBindRecord(this, filter); 364 bindings.put(filter, i); 365 } 366 AppBindRecord a = i.apps.get(app); 367 if (a != null) { 368 return a; 369 } 370 a = new AppBindRecord(this, i, app); 371 i.apps.put(app, a); 372 return a; 373 } 374 hasAutoCreateConnections()375 public boolean hasAutoCreateConnections() { 376 // XXX should probably keep a count of the number of auto-create 377 // connections directly in the service. 378 for (int conni=connections.size()-1; conni>=0; conni--) { 379 ArrayList<ConnectionRecord> cr = connections.valueAt(conni); 380 for (int i=0; i<cr.size(); i++) { 381 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) { 382 return true; 383 } 384 } 385 } 386 return false; 387 } 388 resetRestartCounter()389 public void resetRestartCounter() { 390 restartCount = 0; 391 restartDelay = 0; 392 restartTime = 0; 393 } 394 findDeliveredStart(int id, boolean remove)395 public StartItem findDeliveredStart(int id, boolean remove) { 396 final int N = deliveredStarts.size(); 397 for (int i=0; i<N; i++) { 398 StartItem si = deliveredStarts.get(i); 399 if (si.id == id) { 400 if (remove) deliveredStarts.remove(i); 401 return si; 402 } 403 } 404 405 return null; 406 } 407 getLastStartId()408 public int getLastStartId() { 409 return lastStartId; 410 } 411 makeNextStartId()412 public int makeNextStartId() { 413 lastStartId++; 414 if (lastStartId < 1) { 415 lastStartId = 1; 416 } 417 return lastStartId; 418 } 419 postNotification()420 public void postNotification() { 421 final int appUid = appInfo.uid; 422 final int appPid = app.pid; 423 if (foregroundId != 0 && foregroundNoti != null) { 424 // Do asynchronous communication with notification manager to 425 // avoid deadlocks. 426 final String localPackageName = packageName; 427 final int localForegroundId = foregroundId; 428 final Notification localForegroundNoti = foregroundNoti; 429 ams.mHandler.post(new Runnable() { 430 public void run() { 431 NotificationManagerInternal nm = LocalServices.getService( 432 NotificationManagerInternal.class); 433 if (nm == null) { 434 return; 435 } 436 try { 437 if (localForegroundNoti.icon == 0) { 438 // It is not correct for the caller to supply a notification 439 // icon, but this used to be able to slip through, so for 440 // those dirty apps give it the app's icon. 441 localForegroundNoti.icon = appInfo.icon; 442 443 // Do not allow apps to present a sneaky invisible content view either. 444 localForegroundNoti.contentView = null; 445 localForegroundNoti.bigContentView = null; 446 CharSequence appName = appInfo.loadLabel( 447 ams.mContext.getPackageManager()); 448 if (appName == null) { 449 appName = appInfo.packageName; 450 } 451 Context ctx = null; 452 try { 453 ctx = ams.mContext.createPackageContext( 454 appInfo.packageName, 0); 455 Intent runningIntent = new Intent( 456 Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 457 runningIntent.setData(Uri.fromParts("package", 458 appInfo.packageName, null)); 459 PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0, 460 runningIntent, PendingIntent.FLAG_UPDATE_CURRENT); 461 localForegroundNoti.color = ams.mContext.getResources().getColor( 462 com.android.internal 463 .R.color.system_notification_accent_color); 464 localForegroundNoti.setLatestEventInfo(ctx, 465 ams.mContext.getString( 466 com.android.internal.R.string 467 .app_running_notification_title, 468 appName), 469 ams.mContext.getString( 470 com.android.internal.R.string 471 .app_running_notification_text, 472 appName), 473 pi); 474 } catch (PackageManager.NameNotFoundException e) { 475 localForegroundNoti.icon = 0; 476 } 477 } 478 if (localForegroundNoti.icon == 0) { 479 // Notifications whose icon is 0 are defined to not show 480 // a notification, silently ignoring it. We don't want to 481 // just ignore it, we want to prevent the service from 482 // being foreground. 483 throw new RuntimeException("icon must be non-zero"); 484 } 485 int[] outId = new int[1]; 486 nm.enqueueNotification(localPackageName, localPackageName, 487 appUid, appPid, null, localForegroundId, localForegroundNoti, 488 outId, userId); 489 } catch (RuntimeException e) { 490 Slog.w(ActivityManagerService.TAG, 491 "Error showing notification for service", e); 492 // If it gave us a garbage notification, it doesn't 493 // get to be foreground. 494 ams.setServiceForeground(name, ServiceRecord.this, 495 0, null, true); 496 ams.crashApplication(appUid, appPid, localPackageName, 497 "Bad notification for startForeground: " + e); 498 } 499 } 500 }); 501 } 502 } 503 cancelNotification()504 public void cancelNotification() { 505 if (foregroundId != 0) { 506 // Do asynchronous communication with notification manager to 507 // avoid deadlocks. 508 final String localPackageName = packageName; 509 final int localForegroundId = foregroundId; 510 ams.mHandler.post(new Runnable() { 511 public void run() { 512 INotificationManager inm = NotificationManager.getService(); 513 if (inm == null) { 514 return; 515 } 516 try { 517 inm.cancelNotificationWithTag(localPackageName, null, 518 localForegroundId, userId); 519 } catch (RuntimeException e) { 520 Slog.w(ActivityManagerService.TAG, 521 "Error canceling notification for service", e); 522 } catch (RemoteException e) { 523 } 524 } 525 }); 526 } 527 } 528 stripForegroundServiceFlagFromNotification()529 public void stripForegroundServiceFlagFromNotification() { 530 if (foregroundId == 0) { 531 return; 532 } 533 534 final int localForegroundId = foregroundId; 535 final int localUserId = userId; 536 final String localPackageName = packageName; 537 538 // Do asynchronous communication with notification manager to 539 // avoid deadlocks. 540 ams.mHandler.post(new Runnable() { 541 @Override 542 public void run() { 543 NotificationManagerInternal nmi = LocalServices.getService( 544 NotificationManagerInternal.class); 545 if (nmi == null) { 546 return; 547 } 548 nmi.removeForegroundServiceFlagFromNotification(localPackageName, localForegroundId, 549 localUserId); 550 } 551 }); 552 } 553 clearDeliveredStartsLocked()554 public void clearDeliveredStartsLocked() { 555 for (int i=deliveredStarts.size()-1; i>=0; i--) { 556 deliveredStarts.get(i).removeUriPermissionsLocked(); 557 } 558 deliveredStarts.clear(); 559 } 560 toString()561 public String toString() { 562 if (stringName != null) { 563 return stringName; 564 } 565 StringBuilder sb = new StringBuilder(128); 566 sb.append("ServiceRecord{") 567 .append(Integer.toHexString(System.identityHashCode(this))) 568 .append(" u").append(userId) 569 .append(' ').append(shortName).append('}'); 570 return stringName = sb.toString(); 571 } 572 } 573