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