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