blob: 89761a8860de981a7907d84618ddabc2b653f668 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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;
20
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070021import android.app.INotificationManager;
22import android.app.Notification;
23import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.ComponentName;
25import android.content.Intent;
26import android.content.pm.ApplicationInfo;
27import android.content.pm.ServiceInfo;
28import android.os.Binder;
29import android.os.IBinder;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070030import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.SystemClock;
32
33import java.io.PrintWriter;
34import java.util.ArrayList;
35import java.util.HashMap;
36import java.util.Iterator;
37import java.util.List;
38
39/**
40 * A running application service.
41 */
42class ServiceRecord extends Binder {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080043 final ActivityManagerService ams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 final BatteryStatsImpl.Uid.Pkg.Serv stats;
45 final ComponentName name; // service component.
46 final String shortName; // name.flattenToShortString().
47 final Intent.FilterComparison intent;
48 // original intent used to find service.
49 final ServiceInfo serviceInfo;
50 // all information about the service.
51 final ApplicationInfo appInfo;
52 // information about service's app.
53 final String packageName; // the package implementing intent's component
54 final String processName; // process where this component wants to run
55 final String permission;// permission needed to access service
56 final String baseDir; // where activity source (resources etc) located
57 final String resDir; // where public activity source (public resources etc) located
58 final String dataDir; // where activity data should go
59 final boolean exported; // from ServiceInfo.exported
60 final Runnable restarter; // used to schedule retries of starting the service
61 final long createTime; // when this service was created
62 final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
63 = new HashMap<Intent.FilterComparison, IntentBindRecord>();
64 // All active bindings to the service.
65 final HashMap<IBinder, ConnectionRecord> connections
66 = new HashMap<IBinder, ConnectionRecord>();
67 // IBinder -> ConnectionRecord of all bound clients
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070068
69 // Maximum number of delivery attempts before giving up.
70 static final int MAX_DELIVERY_COUNT = 3;
71
72 // Maximum number of times it can fail during execution before giving up.
73 static final int MAX_DONE_EXECUTING_COUNT = 6;
74
75 static class StartItem {
76 final int id;
77 final Intent intent;
78 long deliveredTime;
79 int deliveryCount;
80 int doneExecutingCount;
81
82 StartItem(int _id, Intent _intent) {
83 id = _id;
84 intent = _intent;
85 }
86 }
87 final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>();
88 // start() arguments which been delivered.
89 final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 // start() arguments that haven't yet been delivered.
91
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070092 ProcessRecord app; // where this service is running or null.
93 boolean isForeground; // is service currently in foreground mode?
94 int foregroundId; // Notification ID of last foreground req.
95 Notification foregroundNoti; // Notification record of foreground state.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 long lastActivity; // last time there was some activity on the service.
97 boolean startRequested; // someone explicitly called start?
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070098 boolean stopIfKilled; // last onStart() said to stop if service killed?
99 boolean callStart; // last onStart() has asked to alway be called on restart.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 int lastStartId; // identifier of most recent start request.
101 int executeNesting; // number of outstanding operations keeping foreground.
102 long executingStart; // start time of last execute request.
103 int crashCount; // number of times proc has crashed with service running
104 int totalRestartCount; // number of times we have had to restart.
105 int restartCount; // number of restarts performed in a row.
106 long restartDelay; // delay until next restart attempt.
107 long restartTime; // time of last restart.
108 long nextRestartTime; // time when restartDelay will expire.
109
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700110 String stringName; // caching of toString
111
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700112 void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) {
113 final int N = list.size();
114 for (int i=0; i<N; i++) {
115 StartItem si = list.get(i);
116 pw.print(prefix); pw.print("#"); pw.print(i);
117 pw.print(" id="); pw.print(si.id);
118 if (now != 0) pw.print(" dur="); pw.print(now-si.deliveredTime);
119 if (si.deliveryCount != 0) {
120 pw.print(" dc="); pw.print(si.deliveryCount);
121 }
122 if (si.doneExecutingCount != 0) {
123 pw.print(" dxc="); pw.print(si.doneExecutingCount);
124 }
125 pw.print(" ");
126 if (si.intent != null) pw.println(si.intent.toString());
127 else pw.println("null");
128 }
129 }
130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700132 pw.print(prefix); pw.print("intent={");
133 pw.print(intent.getIntent().toShortString(true, false));
134 pw.println('}');
135 pw.print(prefix); pw.print("packageName="); pw.println(packageName);
136 pw.print(prefix); pw.print("processName="); pw.println(processName);
137 if (permission != null) {
138 pw.print(prefix); pw.print("permission="); pw.println(permission);
139 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700140 long now = SystemClock.uptimeMillis();
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700141 pw.print(prefix); pw.print("baseDir="); pw.print(baseDir);
142 if (!resDir.equals(baseDir)) pw.print(" resDir="); pw.print(resDir);
143 pw.print(" dataDir="); pw.println(dataDir);
144 pw.print(prefix); pw.print("app="); pw.println(app);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700145 if (isForeground || foregroundId != 0) {
146 pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
147 pw.print(" foregroundId="); pw.print(foregroundId);
148 pw.print(" foregroundNoti="); pw.println(foregroundNoti);
149 }
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -0700150 pw.print(prefix); pw.print("lastActivity="); pw.print(lastActivity-now);
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700151 pw.print(" executingStart="); pw.print(executingStart-now);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700152 pw.print(" restartTime="); pw.println(restartTime);
153 if (startRequested || lastStartId != 0) {
154 pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700155 pw.print(" stopIfKilled="); pw.print(stopIfKilled);
156 pw.print(" callStart="); pw.print(callStart);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700157 pw.print(" lastStartId="); pw.println(lastStartId);
158 }
159 if (executeNesting != 0 || crashCount != 0 || restartCount != 0
160 || restartDelay != 0 || nextRestartTime != 0) {
161 pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting);
162 pw.print(" restartCount="); pw.print(restartCount);
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -0700163 pw.print(" restartDelay="); pw.print(restartDelay-now);
164 pw.print(" nextRestartTime="); pw.print(nextRestartTime-now);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700165 pw.print(" crashCount="); pw.println(crashCount);
166 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700167 if (deliveredStarts.size() > 0) {
168 pw.print(prefix); pw.println("Delivered Starts:");
169 dumpStartList(pw, prefix, deliveredStarts, SystemClock.uptimeMillis());
170 }
171 if (pendingStarts.size() > 0) {
172 pw.print(prefix); pw.println("Pending Starts:");
173 dumpStartList(pw, prefix, pendingStarts, 0);
174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 if (bindings.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 Iterator<IntentBindRecord> it = bindings.values().iterator();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700177 pw.print(prefix); pw.println("Bindings:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 while (it.hasNext()) {
179 IntentBindRecord b = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700180 pw.print(prefix); pw.print("* IntentBindRecord{");
181 pw.print(Integer.toHexString(System.identityHashCode(b)));
182 pw.println("}:");
183 b.dumpInService(pw, prefix + " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 }
185 }
186 if (connections.size() > 0) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700187 pw.print(prefix); pw.println("All Connections:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 Iterator<ConnectionRecord> it = connections.values().iterator();
189 while (it.hasNext()) {
190 ConnectionRecord c = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700191 pw.print(prefix); pw.print(" "); pw.println(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 }
193 }
194 }
195
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800196 ServiceRecord(ActivityManagerService ams,
197 BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800199 this.ams = ams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 this.stats = servStats;
201 this.name = name;
202 shortName = name.flattenToShortString();
203 this.intent = intent;
204 serviceInfo = sInfo;
205 appInfo = sInfo.applicationInfo;
206 packageName = sInfo.applicationInfo.packageName;
207 processName = sInfo.processName;
208 permission = sInfo.permission;
209 baseDir = sInfo.applicationInfo.sourceDir;
210 resDir = sInfo.applicationInfo.publicSourceDir;
211 dataDir = sInfo.applicationInfo.dataDir;
212 exported = sInfo.exported;
213 this.restarter = restarter;
214 createTime = lastActivity = SystemClock.uptimeMillis();
215 }
216
217 public AppBindRecord retrieveAppBindingLocked(Intent intent,
218 ProcessRecord app) {
219 Intent.FilterComparison filter = new Intent.FilterComparison(intent);
220 IntentBindRecord i = bindings.get(filter);
221 if (i == null) {
222 i = new IntentBindRecord(this, filter);
223 bindings.put(filter, i);
224 }
225 AppBindRecord a = i.apps.get(app);
226 if (a != null) {
227 return a;
228 }
229 a = new AppBindRecord(this, i, app);
230 i.apps.put(app, a);
231 return a;
232 }
233
234 public void resetRestartCounter() {
235 restartCount = 0;
236 restartDelay = 0;
237 restartTime = 0;
238 }
239
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700240 public StartItem findDeliveredStart(int id, boolean remove) {
241 final int N = deliveredStarts.size();
242 for (int i=0; i<N; i++) {
243 StartItem si = deliveredStarts.get(i);
244 if (si.id == id) {
245 if (remove) deliveredStarts.remove(i);
246 return si;
247 }
248 }
249
250 return null;
251 }
252
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700253 public void postNotification() {
254 if (foregroundId != 0 && foregroundNoti != null) {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800255 // Do asynchronous communication with notification manager to
256 // avoid deadlocks.
257 final String localPackageName = packageName;
258 final int localForegroundId = foregroundId;
259 final Notification localForegroundNoti = foregroundNoti;
260 ams.mHandler.post(new Runnable() {
261 public void run() {
262 INotificationManager inm = NotificationManager.getService();
263 if (inm == null) {
264 return;
265 }
266 try {
267 int[] outId = new int[1];
268 inm.enqueueNotification(localPackageName, localForegroundId,
269 localForegroundNoti, outId);
270 } catch (RemoteException e) {
271 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700272 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800273 });
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700274 }
275 }
276
277 public void cancelNotification() {
278 if (foregroundId != 0) {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800279 // Do asynchronous communication with notification manager to
280 // avoid deadlocks.
281 final String localPackageName = packageName;
282 final int localForegroundId = foregroundId;
283 ams.mHandler.post(new Runnable() {
284 public void run() {
285 INotificationManager inm = NotificationManager.getService();
286 if (inm == null) {
287 return;
288 }
289 try {
290 inm.cancelNotification(localPackageName, localForegroundId);
291 } catch (RemoteException e) {
292 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700293 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800294 });
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700295 }
296 }
297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700299 if (stringName != null) {
300 return stringName;
301 }
302 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700303 sb.append("ServiceRecord{")
304 .append(Integer.toHexString(System.identityHashCode(this)))
305 .append(' ').append(shortName).append('}');
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700306 return stringName = sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 }
308}