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