ServiceRecord.java revision 742a67127366c376fdf188ff99ba30b27d3bf90c
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.content.ComponentName; 26import android.content.Intent; 27import android.content.pm.ApplicationInfo; 28import android.content.pm.PackageManager; 29import android.content.pm.ServiceInfo; 30import android.os.Binder; 31import android.os.IBinder; 32import android.os.RemoteException; 33import android.os.SystemClock; 34import android.os.UserId; 35import android.util.Slog; 36import android.util.TimeUtils; 37 38import java.io.PrintWriter; 39import java.util.ArrayList; 40import java.util.HashMap; 41import java.util.HashSet; 42import java.util.Iterator; 43import java.util.List; 44 45/** 46 * A running application service. 47 */ 48class ServiceRecord extends Binder { 49 // Maximum number of delivery attempts before giving up. 50 static final int MAX_DELIVERY_COUNT = 3; 51 52 // Maximum number of times it can fail during execution before giving up. 53 static final int MAX_DONE_EXECUTING_COUNT = 6; 54 55 final ActivityManagerService ams; 56 final BatteryStatsImpl.Uid.Pkg.Serv stats; 57 final ComponentName name; // service component. 58 final String shortName; // name.flattenToShortString(). 59 final Intent.FilterComparison intent; 60 // original intent used to find service. 61 final ServiceInfo serviceInfo; 62 // all information about the service. 63 final ApplicationInfo appInfo; 64 // information about service's app. 65 final int userId; // user that this service is running as 66 final String packageName; // the package implementing intent's component 67 final String processName; // process where this component wants to run 68 final String permission;// permission needed to access service 69 final String baseDir; // where activity source (resources etc) located 70 final String resDir; // where public activity source (public resources etc) located 71 final String dataDir; // where activity data should go 72 final boolean exported; // from ServiceInfo.exported 73 final Runnable restarter; // used to schedule retries of starting the service 74 final long createTime; // when this service was created 75 final HashMap<Intent.FilterComparison, IntentBindRecord> bindings 76 = new HashMap<Intent.FilterComparison, IntentBindRecord>(); 77 // All active bindings to the service. 78 final HashMap<IBinder, ArrayList<ConnectionRecord>> connections 79 = new HashMap<IBinder, ArrayList<ConnectionRecord>>(); 80 // IBinder -> ConnectionRecord of all bound clients 81 82 ProcessRecord app; // where this service is running or null. 83 boolean isForeground; // is service currently in foreground mode? 84 int foregroundId; // Notification ID of last foreground req. 85 Notification foregroundNoti; // Notification record of foreground state. 86 long lastActivity; // last time there was some activity on the service. 87 boolean startRequested; // someone explicitly called start? 88 boolean stopIfKilled; // last onStart() said to stop if service killed? 89 boolean callStart; // last onStart() has asked to alway be called on restart. 90 int executeNesting; // number of outstanding operations keeping foreground. 91 long executingStart; // start time of last execute request. 92 int crashCount; // number of times proc has crashed with service running 93 int totalRestartCount; // number of times we have had to restart. 94 int restartCount; // number of restarts performed in a row. 95 long restartDelay; // delay until next restart attempt. 96 long restartTime; // time of last restart. 97 long nextRestartTime; // time when restartDelay will expire. 98 99 String stringName; // caching of toString 100 101 private int lastStartId; // identifier of most recent start request. 102 103 static class StartItem { 104 final ServiceRecord sr; 105 final boolean taskRemoved; 106 final int id; 107 final Intent intent; 108 final int targetPermissionUid; 109 long deliveredTime; 110 int deliveryCount; 111 int doneExecutingCount; 112 UriPermissionOwner uriPermissions; 113 114 String stringName; // caching of toString 115 116 StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent, 117 int _targetPermissionUid) { 118 sr = _sr; 119 taskRemoved = _taskRemoved; 120 id = _id; 121 intent = _intent; 122 targetPermissionUid = _targetPermissionUid; 123 } 124 125 UriPermissionOwner getUriPermissionsLocked() { 126 if (uriPermissions == null) { 127 uriPermissions = new UriPermissionOwner(sr.ams, this); 128 } 129 return uriPermissions; 130 } 131 132 void removeUriPermissionsLocked() { 133 if (uriPermissions != null) { 134 uriPermissions.removeUriPermissionsLocked(); 135 uriPermissions = null; 136 } 137 } 138 139 public String toString() { 140 if (stringName != null) { 141 return stringName; 142 } 143 StringBuilder sb = new StringBuilder(128); 144 sb.append("ServiceRecord{") 145 .append(Integer.toHexString(System.identityHashCode(sr))) 146 .append(' ').append(sr.shortName) 147 .append(" StartItem ") 148 .append(Integer.toHexString(System.identityHashCode(this))) 149 .append(" id=").append(id).append('}'); 150 return stringName = sb.toString(); 151 } 152 } 153 154 final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>(); 155 // start() arguments which been delivered. 156 final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>(); 157 // start() arguments that haven't yet been delivered. 158 159 void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) { 160 final int N = list.size(); 161 for (int i=0; i<N; i++) { 162 StartItem si = list.get(i); 163 pw.print(prefix); pw.print("#"); pw.print(i); 164 pw.print(" id="); pw.print(si.id); 165 if (now != 0) { 166 pw.print(" dur="); 167 TimeUtils.formatDuration(si.deliveredTime, now, pw); 168 } 169 if (si.deliveryCount != 0) { 170 pw.print(" dc="); pw.print(si.deliveryCount); 171 } 172 if (si.doneExecutingCount != 0) { 173 pw.print(" dxc="); pw.print(si.doneExecutingCount); 174 } 175 pw.println(""); 176 pw.print(prefix); pw.print(" intent="); 177 if (si.intent != null) pw.println(si.intent.toString()); 178 else pw.println("null"); 179 if (si.targetPermissionUid >= 0) { 180 pw.print(prefix); pw.print(" targetPermissionUid="); 181 pw.println(si.targetPermissionUid); 182 } 183 if (si.uriPermissions != null) { 184 if (si.uriPermissions.readUriPermissions != null) { 185 pw.print(prefix); pw.print(" readUriPermissions="); 186 pw.println(si.uriPermissions.readUriPermissions); 187 } 188 if (si.uriPermissions.writeUriPermissions != null) { 189 pw.print(prefix); pw.print(" writeUriPermissions="); 190 pw.println(si.uriPermissions.writeUriPermissions); 191 } 192 } 193 } 194 } 195 196 void dump(PrintWriter pw, String prefix) { 197 pw.print(prefix); pw.print("intent={"); 198 pw.print(intent.getIntent().toShortString(false, true, false)); 199 pw.println('}'); 200 pw.print(prefix); pw.print("packageName="); pw.println(packageName); 201 pw.print(prefix); pw.print("processName="); pw.println(processName); 202 if (permission != null) { 203 pw.print(prefix); pw.print("permission="); pw.println(permission); 204 } 205 long now = SystemClock.uptimeMillis(); 206 long nowReal = SystemClock.elapsedRealtime(); 207 pw.print(prefix); pw.print("baseDir="); pw.println(baseDir); 208 if (!resDir.equals(baseDir)) { 209 pw.print(prefix); pw.print("resDir="); pw.println(resDir); 210 } 211 pw.print(prefix); pw.print("dataDir="); pw.println(dataDir); 212 pw.print(prefix); pw.print("app="); pw.println(app); 213 if (isForeground || foregroundId != 0) { 214 pw.print(prefix); pw.print("isForeground="); pw.print(isForeground); 215 pw.print(" foregroundId="); pw.print(foregroundId); 216 pw.print(" foregroundNoti="); pw.println(foregroundNoti); 217 } 218 pw.print(prefix); pw.print("createTime="); 219 TimeUtils.formatDuration(createTime, nowReal, pw); 220 pw.print(" lastActivity="); 221 TimeUtils.formatDuration(lastActivity, now, pw); 222 pw.println(""); 223 pw.print(prefix); pw.print("executingStart="); 224 TimeUtils.formatDuration(executingStart, now, pw); 225 pw.print(" restartTime="); 226 TimeUtils.formatDuration(restartTime, now, pw); 227 pw.println(""); 228 if (startRequested || lastStartId != 0) { 229 pw.print(prefix); pw.print("startRequested="); pw.print(startRequested); 230 pw.print(" stopIfKilled="); pw.print(stopIfKilled); 231 pw.print(" callStart="); pw.print(callStart); 232 pw.print(" lastStartId="); pw.println(lastStartId); 233 } 234 if (executeNesting != 0 || crashCount != 0 || restartCount != 0 235 || restartDelay != 0 || nextRestartTime != 0) { 236 pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting); 237 pw.print(" restartCount="); pw.print(restartCount); 238 pw.print(" restartDelay="); 239 TimeUtils.formatDuration(restartDelay, now, pw); 240 pw.print(" nextRestartTime="); 241 TimeUtils.formatDuration(nextRestartTime, now, pw); 242 pw.print(" crashCount="); pw.println(crashCount); 243 } 244 if (deliveredStarts.size() > 0) { 245 pw.print(prefix); pw.println("Delivered Starts:"); 246 dumpStartList(pw, prefix, deliveredStarts, now); 247 } 248 if (pendingStarts.size() > 0) { 249 pw.print(prefix); pw.println("Pending Starts:"); 250 dumpStartList(pw, prefix, pendingStarts, 0); 251 } 252 if (bindings.size() > 0) { 253 Iterator<IntentBindRecord> it = bindings.values().iterator(); 254 pw.print(prefix); pw.println("Bindings:"); 255 while (it.hasNext()) { 256 IntentBindRecord b = it.next(); 257 pw.print(prefix); pw.print("* IntentBindRecord{"); 258 pw.print(Integer.toHexString(System.identityHashCode(b))); 259 pw.println("}:"); 260 b.dumpInService(pw, prefix + " "); 261 } 262 } 263 if (connections.size() > 0) { 264 pw.print(prefix); pw.println("All Connections:"); 265 Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator(); 266 while (it.hasNext()) { 267 ArrayList<ConnectionRecord> c = it.next(); 268 for (int i=0; i<c.size(); i++) { 269 pw.print(prefix); pw.print(" "); pw.println(c.get(i)); 270 } 271 } 272 } 273 } 274 275 ServiceRecord(ActivityManagerService ams, 276 BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name, 277 Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) { 278 this.ams = ams; 279 this.stats = servStats; 280 this.name = name; 281 shortName = name.flattenToShortString(); 282 this.intent = intent; 283 serviceInfo = sInfo; 284 appInfo = sInfo.applicationInfo; 285 packageName = sInfo.applicationInfo.packageName; 286 processName = sInfo.processName; 287 permission = sInfo.permission; 288 baseDir = sInfo.applicationInfo.sourceDir; 289 resDir = sInfo.applicationInfo.publicSourceDir; 290 dataDir = sInfo.applicationInfo.dataDir; 291 exported = sInfo.exported; 292 this.restarter = restarter; 293 createTime = SystemClock.elapsedRealtime(); 294 lastActivity = SystemClock.uptimeMillis(); 295 userId = UserId.getUserId(appInfo.uid); 296 } 297 298 public AppBindRecord retrieveAppBindingLocked(Intent intent, 299 ProcessRecord app) { 300 Intent.FilterComparison filter = new Intent.FilterComparison(intent); 301 IntentBindRecord i = bindings.get(filter); 302 if (i == null) { 303 i = new IntentBindRecord(this, filter); 304 bindings.put(filter, i); 305 } 306 AppBindRecord a = i.apps.get(app); 307 if (a != null) { 308 return a; 309 } 310 a = new AppBindRecord(this, i, app); 311 i.apps.put(app, a); 312 return a; 313 } 314 315 public void resetRestartCounter() { 316 restartCount = 0; 317 restartDelay = 0; 318 restartTime = 0; 319 } 320 321 public StartItem findDeliveredStart(int id, boolean remove) { 322 final int N = deliveredStarts.size(); 323 for (int i=0; i<N; i++) { 324 StartItem si = deliveredStarts.get(i); 325 if (si.id == id) { 326 if (remove) deliveredStarts.remove(i); 327 return si; 328 } 329 } 330 331 return null; 332 } 333 334 public int getLastStartId() { 335 return lastStartId; 336 } 337 338 public int makeNextStartId() { 339 lastStartId++; 340 if (lastStartId < 1) { 341 lastStartId = 1; 342 } 343 return lastStartId; 344 } 345 346 public void postNotification() { 347 final int appUid = appInfo.uid; 348 final int appPid = app.pid; 349 if (foregroundId != 0 && foregroundNoti != null) { 350 // Do asynchronous communication with notification manager to 351 // avoid deadlocks. 352 final String localPackageName = packageName; 353 final int localForegroundId = foregroundId; 354 final Notification localForegroundNoti = foregroundNoti; 355 ams.mHandler.post(new Runnable() { 356 public void run() { 357 NotificationManagerService nm = 358 (NotificationManagerService) NotificationManager.getService(); 359 if (nm == null) { 360 return; 361 } 362 try { 363 int[] outId = new int[1]; 364 nm.enqueueNotificationInternal(localPackageName, appUid, appPid, 365 null, localForegroundId, localForegroundNoti, outId); 366 } catch (RuntimeException e) { 367 Slog.w(ActivityManagerService.TAG, 368 "Error showing notification for service", e); 369 // If it gave us a garbage notification, it doesn't 370 // get to be foreground. 371 ams.setServiceForeground(name, ServiceRecord.this, 372 0, null, true); 373 ams.crashApplication(appUid, appPid, localPackageName, 374 "Bad notification for startForeground: " + e); 375 } 376 } 377 }); 378 } 379 } 380 381 public void cancelNotification() { 382 if (foregroundId != 0) { 383 // Do asynchronous communication with notification manager to 384 // avoid deadlocks. 385 final String localPackageName = packageName; 386 final int localForegroundId = foregroundId; 387 ams.mHandler.post(new Runnable() { 388 public void run() { 389 INotificationManager inm = NotificationManager.getService(); 390 if (inm == null) { 391 return; 392 } 393 try { 394 inm.cancelNotification(localPackageName, localForegroundId); 395 } catch (RuntimeException e) { 396 Slog.w(ActivityManagerService.TAG, 397 "Error canceling notification for service", e); 398 } catch (RemoteException e) { 399 } 400 } 401 }); 402 } 403 } 404 405 public void clearDeliveredStartsLocked() { 406 for (int i=deliveredStarts.size()-1; i>=0; i--) { 407 deliveredStarts.get(i).removeUriPermissionsLocked(); 408 } 409 deliveredStarts.clear(); 410 } 411 412 public String toString() { 413 if (stringName != null) { 414 return stringName; 415 } 416 StringBuilder sb = new StringBuilder(128); 417 sb.append("ServiceRecord{") 418 .append(Integer.toHexString(System.identityHashCode(this))) 419 .append(' ').append(shortName).append('}'); 420 return stringName = sb.toString(); 421 } 422} 423