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