blob: f296c6045248642dc59ae874ee2ab2fb0d333e85 [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
Joe Onorato4eb64fd2016-03-21 15:30:09 -070019import com.android.internal.app.procstats.ServiceState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Adam Lesinski182f73f2013-12-05 16:48:06 -080021import com.android.server.LocalServices;
22import com.android.server.notification.NotificationManagerInternal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070024import android.app.INotificationManager;
25import android.app.Notification;
26import android.app.NotificationManager;
Dianne Hackborn390517b2013-05-30 15:03:32 -070027import android.app.PendingIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.content.ComponentName;
Dianne Hackborn0c380492012-08-20 17:23:30 -070029import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.Intent;
31import android.content.pm.ApplicationInfo;
Amith Yamasani742a6712011-05-04 14:49:28 -070032import android.content.pm.PackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.content.pm.ServiceInfo;
Dianne Hackborn390517b2013-05-30 15:03:32 -070034import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.Binder;
Julia Reynolds5a4399a2017-10-11 08:44:46 -040036import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.os.IBinder;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070038import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070040import android.os.UserHandle;
Dianne Hackborn390517b2013-05-30 15:03:32 -070041import android.provider.Settings;
42import android.util.ArrayMap;
Joe Onorato8a9b2202010-02-26 18:56:32 -080043import android.util.Slog;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070044import android.util.TimeUtils;
Yi Jin6b514142017-10-30 14:54:12 -070045import android.util.proto.ProtoOutputStream;
46import android.util.proto.ProtoUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
48import java.io.PrintWriter;
49import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.util.List;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070051import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052
Wale Ogunwalee23149f2015-03-06 15:39:44 -080053import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
54import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
55
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056/**
57 * A running application service.
58 */
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070059final class ServiceRecord extends Binder {
Wale Ogunwalee23149f2015-03-06 15:39:44 -080060 private static final String TAG = TAG_WITH_CLASS_NAME ? "ServiceRecord" : TAG_AM;
61
Dianne Hackborn39792d22010-08-19 18:01:52 -070062 // Maximum number of delivery attempts before giving up.
63 static final int MAX_DELIVERY_COUNT = 3;
64
65 // Maximum number of times it can fail during execution before giving up.
66 static final int MAX_DONE_EXECUTING_COUNT = 6;
67
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080068 final ActivityManagerService ams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 final BatteryStatsImpl.Uid.Pkg.Serv stats;
70 final ComponentName name; // service component.
71 final String shortName; // name.flattenToShortString().
72 final Intent.FilterComparison intent;
73 // original intent used to find service.
74 final ServiceInfo serviceInfo;
75 // all information about the service.
76 final ApplicationInfo appInfo;
77 // information about service's app.
Amith Yamasani742a6712011-05-04 14:49:28 -070078 final int userId; // user that this service is running as
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 final String packageName; // the package implementing intent's component
80 final String processName; // process where this component wants to run
81 final String permission;// permission needed to access service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 final boolean exported; // from ServiceInfo.exported
83 final Runnable restarter; // used to schedule retries of starting the service
Yi Jin6b514142017-10-30 14:54:12 -070084 final long createRealTime; // when this service was created
Dianne Hackborn390517b2013-05-30 15:03:32 -070085 final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
86 = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 // All active bindings to the service.
Dianne Hackborn390517b2013-05-30 15:03:32 -070088 final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
89 = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 // IBinder -> ConnectionRecord of all bound clients
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070092 ProcessRecord app; // where this service is running or null.
Dianne Hackborna0c283e2012-02-09 10:47:01 -080093 ProcessRecord isolatedProc; // keep track of isolated process, if requested
Joe Onorato4eb64fd2016-03-21 15:30:09 -070094 ServiceState tracker; // tracking service execution, may be null
95 ServiceState restartTracker; // tracking service restart
Dianne Hackborna590d2b2016-06-27 15:07:18 -070096 boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
Dianne Hackborn9210bc82013-09-05 12:31:16 -070097 boolean delayed; // are we waiting to start this service in the background?
Christopher Tate08992ac2017-03-21 11:37:06 -070098 boolean fgRequired; // is the service required to go foreground after starting?
99 boolean fgWaiting; // is a timeout for going foreground already scheduled?
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700100 boolean isForeground; // is service currently in foreground mode?
101 int foregroundId; // Notification ID of last foreground req.
102 Notification foregroundNoti; // Notification record of foreground state.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 long lastActivity; // last time there was some activity on the service.
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700104 long startingBgTimeout; // time at which we scheduled this for a delayed start.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 boolean startRequested; // someone explicitly called start?
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700106 boolean delayedStop; // service has been stopped but is in a delayed start?
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700107 boolean stopIfKilled; // last onStart() said to stop if service killed?
Yi Jin6b514142017-10-30 14:54:12 -0700108 boolean callStart; // last onStart() has asked to always be called on restart.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 int executeNesting; // number of outstanding operations keeping foreground.
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700110 boolean executeFg; // should we be executing in the foreground?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 long executingStart; // start time of last execute request.
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700112 boolean createdFromFg; // was this service last created due to a foreground process call?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 int crashCount; // number of times proc has crashed with service running
114 int totalRestartCount; // number of times we have had to restart.
115 int restartCount; // number of restarts performed in a row.
116 long restartDelay; // delay until next restart attempt.
117 long restartTime; // time of last restart.
118 long nextRestartTime; // time when restartDelay will expire.
Dianne Hackborn455625e2015-01-21 09:55:13 -0800119 boolean destroying; // set when we have started destroying the service
Craig Mautner66c4a822015-01-16 12:48:16 -0800120 long destroyTime; // time at which destory was initiated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700122 String stringName; // caching of toString
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500123
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700124 private int lastStartId; // identifier of most recent start request.
125
Dianne Hackborn7e269642010-08-25 19:50:20 -0700126 static class StartItem {
Dianne Hackborn39792d22010-08-19 18:01:52 -0700127 final ServiceRecord sr;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700128 final boolean taskRemoved;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700129 final int id;
Todd Kennedy51b3aac2017-03-30 17:50:42 -0700130 final int callingId;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700131 final Intent intent;
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800132 final ActivityManagerService.NeededUriGrants neededGrants;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700133 long deliveredTime;
134 int deliveryCount;
135 int doneExecutingCount;
Dianne Hackborn7e269642010-08-25 19:50:20 -0700136 UriPermissionOwner uriPermissions;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700137
138 String stringName; // caching of toString
139
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700140 StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent,
Todd Kennedy51b3aac2017-03-30 17:50:42 -0700141 ActivityManagerService.NeededUriGrants _neededGrants, int _callingId) {
Dianne Hackborn39792d22010-08-19 18:01:52 -0700142 sr = _sr;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700143 taskRemoved = _taskRemoved;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700144 id = _id;
145 intent = _intent;
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800146 neededGrants = _neededGrants;
Todd Kennedy51b3aac2017-03-30 17:50:42 -0700147 callingId = _callingId;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700148 }
149
Dianne Hackborn7e269642010-08-25 19:50:20 -0700150 UriPermissionOwner getUriPermissionsLocked() {
151 if (uriPermissions == null) {
152 uriPermissions = new UriPermissionOwner(sr.ams, this);
153 }
154 return uriPermissions;
155 }
156
Dianne Hackborn39792d22010-08-19 18:01:52 -0700157 void removeUriPermissionsLocked() {
Dianne Hackborn7e269642010-08-25 19:50:20 -0700158 if (uriPermissions != null) {
159 uriPermissions.removeUriPermissionsLocked();
160 uriPermissions = null;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700161 }
162 }
163
Yi Jin6b514142017-10-30 14:54:12 -0700164 public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
165 long token = proto.start(fieldId);
Yi Jin163967f2018-03-15 13:49:44 -0700166 proto.write(ServiceRecordProto.StartItem.ID, id);
Yi Jin6b514142017-10-30 14:54:12 -0700167 ProtoUtils.toDuration(proto,
Yi Jin163967f2018-03-15 13:49:44 -0700168 ServiceRecordProto.StartItem.DURATION, deliveredTime, now);
169 proto.write(ServiceRecordProto.StartItem.DELIVERY_COUNT, deliveryCount);
170 proto.write(ServiceRecordProto.StartItem.DONE_EXECUTING_COUNT, doneExecutingCount);
Yi Jin6b514142017-10-30 14:54:12 -0700171 if (intent != null) {
Yi Jin163967f2018-03-15 13:49:44 -0700172 intent.writeToProto(proto, ServiceRecordProto.StartItem.INTENT, true, true,
Yi Jin6b514142017-10-30 14:54:12 -0700173 true, false);
174 }
175 if (neededGrants != null) {
Yi Jin163967f2018-03-15 13:49:44 -0700176 neededGrants.writeToProto(proto, ServiceRecordProto.StartItem.NEEDED_GRANTS);
Yi Jin6b514142017-10-30 14:54:12 -0700177 }
178 if (uriPermissions != null) {
Yi Jin163967f2018-03-15 13:49:44 -0700179 uriPermissions.writeToProto(proto, ServiceRecordProto.StartItem.URI_PERMISSIONS);
Yi Jin6b514142017-10-30 14:54:12 -0700180 }
181 proto.end(token);
182 }
183
Dianne Hackborn39792d22010-08-19 18:01:52 -0700184 public String toString() {
185 if (stringName != null) {
186 return stringName;
187 }
188 StringBuilder sb = new StringBuilder(128);
189 sb.append("ServiceRecord{")
190 .append(Integer.toHexString(System.identityHashCode(sr)))
191 .append(' ').append(sr.shortName)
192 .append(" StartItem ")
193 .append(Integer.toHexString(System.identityHashCode(this)))
194 .append(" id=").append(id).append('}');
195 return stringName = sb.toString();
196 }
197 }
198
199 final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>();
200 // start() arguments which been delivered.
201 final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
202 // start() arguments that haven't yet been delivered.
203
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700204 void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) {
205 final int N = list.size();
206 for (int i=0; i<N; i++) {
207 StartItem si = list.get(i);
208 pw.print(prefix); pw.print("#"); pw.print(i);
209 pw.print(" id="); pw.print(si.id);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700210 if (now != 0) {
211 pw.print(" dur=");
212 TimeUtils.formatDuration(si.deliveredTime, now, pw);
213 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700214 if (si.deliveryCount != 0) {
215 pw.print(" dc="); pw.print(si.deliveryCount);
216 }
217 if (si.doneExecutingCount != 0) {
218 pw.print(" dxc="); pw.print(si.doneExecutingCount);
219 }
Dianne Hackborn39792d22010-08-19 18:01:52 -0700220 pw.println("");
221 pw.print(prefix); pw.print(" intent=");
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700222 if (si.intent != null) pw.println(si.intent.toString());
223 else pw.println("null");
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800224 if (si.neededGrants != null) {
225 pw.print(prefix); pw.print(" neededGrants=");
226 pw.println(si.neededGrants);
Dianne Hackborn39792d22010-08-19 18:01:52 -0700227 }
Dianne Hackborn7e269642010-08-25 19:50:20 -0700228 if (si.uriPermissions != null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700229 si.uriPermissions.dump(pw, prefix);
Dianne Hackborn39792d22010-08-19 18:01:52 -0700230 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700231 }
232 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500233
Yi Jin6b514142017-10-30 14:54:12 -0700234 void writeToProto(ProtoOutputStream proto, long fieldId) {
235 long token = proto.start(fieldId);
236 proto.write(ServiceRecordProto.SHORT_NAME, this.shortName);
Yi Jin6b514142017-10-30 14:54:12 -0700237 proto.write(ServiceRecordProto.IS_RUNNING, app != null);
238 if (app != null) {
239 proto.write(ServiceRecordProto.PID, app.pid);
240 }
241 if (intent != null) {
242 intent.getIntent().writeToProto(proto, ServiceRecordProto.INTENT, false, true, false,
243 true);
244 }
245 proto.write(ServiceRecordProto.PACKAGE_NAME, packageName);
246 proto.write(ServiceRecordProto.PROCESS_NAME, processName);
247 proto.write(ServiceRecordProto.PERMISSION, permission);
248
249 long now = SystemClock.uptimeMillis();
250 long nowReal = SystemClock.elapsedRealtime();
251 if (appInfo != null) {
252 long appInfoToken = proto.start(ServiceRecordProto.APPINFO);
253 proto.write(ServiceRecordProto.AppInfo.BASE_DIR, appInfo.sourceDir);
254 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
255 proto.write(ServiceRecordProto.AppInfo.RES_DIR, appInfo.publicSourceDir);
256 }
257 proto.write(ServiceRecordProto.AppInfo.DATA_DIR, appInfo.dataDir);
258 proto.end(appInfoToken);
259 }
260 if (app != null) {
261 app.writeToProto(proto, ServiceRecordProto.APP);
262 }
263 if (isolatedProc != null) {
264 isolatedProc.writeToProto(proto, ServiceRecordProto.ISOLATED_PROC);
265 }
266 proto.write(ServiceRecordProto.WHITELIST_MANAGER, whitelistManager);
267 proto.write(ServiceRecordProto.DELAYED, delayed);
268 if (isForeground || foregroundId != 0) {
269 long fgToken = proto.start(ServiceRecordProto.FOREGROUND);
270 proto.write(ServiceRecordProto.Foreground.ID, foregroundId);
271 foregroundNoti.writeToProto(proto, ServiceRecordProto.Foreground.NOTIFICATION);
272 proto.end(fgToken);
273 }
274 ProtoUtils.toDuration(proto, ServiceRecordProto.CREATE_REAL_TIME, createRealTime, nowReal);
275 ProtoUtils.toDuration(proto,
276 ServiceRecordProto.STARTING_BG_TIMEOUT, startingBgTimeout, now);
277 ProtoUtils.toDuration(proto, ServiceRecordProto.LAST_ACTIVITY_TIME, lastActivity, now);
278 ProtoUtils.toDuration(proto, ServiceRecordProto.RESTART_TIME, restartTime, now);
279 proto.write(ServiceRecordProto.CREATED_FROM_FG, createdFromFg);
280
281 if (startRequested || delayedStop || lastStartId != 0) {
282 long startToken = proto.start(ServiceRecordProto.START);
283 proto.write(ServiceRecordProto.Start.START_REQUESTED, startRequested);
284 proto.write(ServiceRecordProto.Start.DELAYED_STOP, delayedStop);
285 proto.write(ServiceRecordProto.Start.STOP_IF_KILLED, stopIfKilled);
286 proto.write(ServiceRecordProto.Start.LAST_START_ID, lastStartId);
287 proto.end(startToken);
288 }
289
290 if (executeNesting != 0) {
291 long executNestingToken = proto.start(ServiceRecordProto.EXECUTE);
292 proto.write(ServiceRecordProto.ExecuteNesting.EXECUTE_NESTING, executeNesting);
293 proto.write(ServiceRecordProto.ExecuteNesting.EXECUTE_FG, executeFg);
294 ProtoUtils.toDuration(proto,
295 ServiceRecordProto.ExecuteNesting.EXECUTING_START, executingStart, now);
296 proto.end(executNestingToken);
297 }
298 if (destroying || destroyTime != 0) {
299 ProtoUtils.toDuration(proto, ServiceRecordProto.DESTORY_TIME, destroyTime, now);
300 }
301 if (crashCount != 0 || restartCount != 0 || restartDelay != 0 || nextRestartTime != 0) {
302 long crashToken = proto.start(ServiceRecordProto.CRASH);
303 proto.write(ServiceRecordProto.Crash.RESTART_COUNT, restartCount);
304 ProtoUtils.toDuration(proto, ServiceRecordProto.Crash.RESTART_DELAY, restartDelay, now);
305 ProtoUtils.toDuration(proto,
306 ServiceRecordProto.Crash.NEXT_RESTART_TIME, nextRestartTime, now);
307 proto.write(ServiceRecordProto.Crash.CRASH_COUNT, crashCount);
308 proto.end(crashToken);
309 }
310
311 if (deliveredStarts.size() > 0) {
312 final int N = deliveredStarts.size();
313 for (int i = 0; i < N; i++) {
314 deliveredStarts.get(i).writeToProto(proto,
315 ServiceRecordProto.DELIVERED_STARTS, now);
316 }
317 }
318 if (pendingStarts.size() > 0) {
319 final int N = pendingStarts.size();
320 for (int i = 0; i < N; i++) {
321 pendingStarts.get(i).writeToProto(proto, ServiceRecordProto.PENDING_STARTS, now);
322 }
323 }
324 if (bindings.size() > 0) {
325 final int N = bindings.size();
326 for (int i=0; i<N; i++) {
327 IntentBindRecord b = bindings.valueAt(i);
328 b.writeToProto(proto, ServiceRecordProto.BINDINGS);
329 }
330 }
331 if (connections.size() > 0) {
332 final int N = connections.size();
333 for (int conni=0; conni<N; conni++) {
334 ArrayList<ConnectionRecord> c = connections.valueAt(conni);
335 for (int i=0; i<c.size(); i++) {
336 c.get(i).writeToProto(proto, ServiceRecordProto.CONNECTIONS);
337 }
338 }
339 }
340 proto.end(token);
341 }
342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700344 pw.print(prefix); pw.print("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800345 pw.print(intent.getIntent().toShortString(false, true, false, true));
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700346 pw.println('}');
347 pw.print(prefix); pw.print("packageName="); pw.println(packageName);
348 pw.print(prefix); pw.print("processName="); pw.println(processName);
349 if (permission != null) {
350 pw.print(prefix); pw.print("permission="); pw.println(permission);
351 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700352 long now = SystemClock.uptimeMillis();
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700353 long nowReal = SystemClock.elapsedRealtime();
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700354 if (appInfo != null) {
355 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
356 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
357 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
358 }
359 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
Marco Nelissena301fe62011-05-04 08:44:59 -0700360 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700361 pw.print(prefix); pw.print("app="); pw.println(app);
Dianne Hackborna0c283e2012-02-09 10:47:01 -0800362 if (isolatedProc != null) {
363 pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
364 }
Dianne Hackborna590d2b2016-06-27 15:07:18 -0700365 if (whitelistManager) {
366 pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
367 }
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700368 if (delayed) {
369 pw.print(prefix); pw.print("delayed="); pw.println(delayed);
370 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700371 if (isForeground || foregroundId != 0) {
372 pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
373 pw.print(" foregroundId="); pw.print(foregroundId);
374 pw.print(" foregroundNoti="); pw.println(foregroundNoti);
375 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700376 pw.print(prefix); pw.print("createTime=");
Yi Jin6b514142017-10-30 14:54:12 -0700377 TimeUtils.formatDuration(createRealTime, nowReal, pw);
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700378 pw.print(" startingBgTimeout=");
379 TimeUtils.formatDuration(startingBgTimeout, now, pw);
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700380 pw.println();
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700381 pw.print(prefix); pw.print("lastActivity=");
382 TimeUtils.formatDuration(lastActivity, now, pw);
383 pw.print(" restartTime=");
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700384 TimeUtils.formatDuration(restartTime, now, pw);
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700385 pw.print(" createdFromFg="); pw.println(createdFromFg);
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700386 if (startRequested || delayedStop || lastStartId != 0) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700387 pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
Dianne Hackborn9210bc82013-09-05 12:31:16 -0700388 pw.print(" delayedStop="); pw.print(delayedStop);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700389 pw.print(" stopIfKilled="); pw.print(stopIfKilled);
390 pw.print(" callStart="); pw.print(callStart);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700391 pw.print(" lastStartId="); pw.println(lastStartId);
392 }
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700393 if (executeNesting != 0) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700394 pw.print(prefix); pw.print("executeNesting="); pw.print(executeNesting);
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700395 pw.print(" executeFg="); pw.print(executeFg);
396 pw.print(" executingStart=");
397 TimeUtils.formatDuration(executingStart, now, pw);
Dianne Hackborn2be00932013-09-22 16:46:00 -0700398 pw.println();
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700399 }
Dianne Hackborn455625e2015-01-21 09:55:13 -0800400 if (destroying || destroyTime != 0) {
401 pw.print(prefix); pw.print("destroying="); pw.print(destroying);
402 pw.print(" destroyTime=");
403 TimeUtils.formatDuration(destroyTime, now, pw);
404 pw.println();
Craig Mautner66c4a822015-01-16 12:48:16 -0800405 }
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700406 if (crashCount != 0 || restartCount != 0
407 || restartDelay != 0 || nextRestartTime != 0) {
408 pw.print(prefix); pw.print("restartCount="); pw.print(restartCount);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700409 pw.print(" restartDelay=");
410 TimeUtils.formatDuration(restartDelay, now, pw);
411 pw.print(" nextRestartTime=");
412 TimeUtils.formatDuration(nextRestartTime, now, pw);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700413 pw.print(" crashCount="); pw.println(crashCount);
414 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700415 if (deliveredStarts.size() > 0) {
416 pw.print(prefix); pw.println("Delivered Starts:");
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700417 dumpStartList(pw, prefix, deliveredStarts, now);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700418 }
419 if (pendingStarts.size() > 0) {
420 pw.print(prefix); pw.println("Pending Starts:");
421 dumpStartList(pw, prefix, pendingStarts, 0);
422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 if (bindings.size() > 0) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700424 pw.print(prefix); pw.println("Bindings:");
Dianne Hackborn390517b2013-05-30 15:03:32 -0700425 for (int i=0; i<bindings.size(); i++) {
426 IntentBindRecord b = bindings.valueAt(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700427 pw.print(prefix); pw.print("* IntentBindRecord{");
428 pw.print(Integer.toHexString(System.identityHashCode(b)));
Dianne Hackborn0c380492012-08-20 17:23:30 -0700429 if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
430 pw.append(" CREATE");
431 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700432 pw.println("}:");
433 b.dumpInService(pw, prefix + " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 }
435 }
436 if (connections.size() > 0) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700437 pw.print(prefix); pw.println("All Connections:");
Dianne Hackborn390517b2013-05-30 15:03:32 -0700438 for (int conni=0; conni<connections.size(); conni++) {
439 ArrayList<ConnectionRecord> c = connections.valueAt(conni);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700440 for (int i=0; i<c.size(); i++) {
441 pw.print(prefix); pw.print(" "); pw.println(c.get(i));
442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 }
444 }
445 }
446
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800447 ServiceRecord(ActivityManagerService ams,
448 BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700449 Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
450 Runnable restarter) {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800451 this.ams = ams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 this.stats = servStats;
453 this.name = name;
454 shortName = name.flattenToShortString();
455 this.intent = intent;
456 serviceInfo = sInfo;
457 appInfo = sInfo.applicationInfo;
458 packageName = sInfo.applicationInfo.packageName;
459 processName = sInfo.processName;
460 permission = sInfo.permission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 exported = sInfo.exported;
462 this.restarter = restarter;
Yi Jin6b514142017-10-30 14:54:12 -0700463 createRealTime = SystemClock.elapsedRealtime();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700464 lastActivity = SystemClock.uptimeMillis();
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700465 userId = UserHandle.getUserId(appInfo.uid);
Dianne Hackbornbf36ee22013-07-26 18:24:10 -0700466 createdFromFg = callerIsFg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 }
468
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700469 public ServiceState getTracker() {
Dianne Hackbornbd754f42013-07-23 15:52:36 -0700470 if (tracker != null) {
471 return tracker;
472 }
473 if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700474 tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
Dianne Hackborn8472e612014-01-23 17:57:20 -0800475 serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode,
476 serviceInfo.processName, serviceInfo.name);
Dianne Hackborn164371f2013-10-01 19:10:13 -0700477 tracker.applyNewOwner(this);
Dianne Hackbornbd754f42013-07-23 15:52:36 -0700478 }
479 return tracker;
480 }
481
Dianne Hackborn164371f2013-10-01 19:10:13 -0700482 public void forceClearTracker() {
483 if (tracker != null) {
Dianne Hackborn878deb32013-10-14 16:55:09 -0700484 tracker.clearCurrentOwner(this, true);
Dianne Hackborn164371f2013-10-01 19:10:13 -0700485 tracker = null;
486 }
487 }
488
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800489 public void makeRestarting(int memFactor, long now) {
490 if (restartTracker == null) {
491 if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
492 restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
Dianne Hackborn8472e612014-01-23 17:57:20 -0800493 serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.versionCode,
494 serviceInfo.processName, serviceInfo.name);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800495 }
496 if (restartTracker == null) {
497 return;
498 }
499 }
500 restartTracker.setRestarting(true, memFactor, now);
501 }
502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 public AppBindRecord retrieveAppBindingLocked(Intent intent,
504 ProcessRecord app) {
505 Intent.FilterComparison filter = new Intent.FilterComparison(intent);
506 IntentBindRecord i = bindings.get(filter);
507 if (i == null) {
508 i = new IntentBindRecord(this, filter);
509 bindings.put(filter, i);
510 }
511 AppBindRecord a = i.apps.get(app);
512 if (a != null) {
513 return a;
514 }
515 a = new AppBindRecord(this, i, app);
516 i.apps.put(app, a);
517 return a;
518 }
519
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700520 public boolean hasAutoCreateConnections() {
521 // XXX should probably keep a count of the number of auto-create
522 // connections directly in the service.
523 for (int conni=connections.size()-1; conni>=0; conni--) {
524 ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
525 for (int i=0; i<cr.size(); i++) {
526 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
527 return true;
528 }
529 }
530 }
531 return false;
532 }
533
Dianne Hackborna590d2b2016-06-27 15:07:18 -0700534 public void updateWhitelistManager() {
535 whitelistManager = false;
536 for (int conni=connections.size()-1; conni>=0; conni--) {
537 ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
538 for (int i=0; i<cr.size(); i++) {
539 if ((cr.get(i).flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
540 whitelistManager = true;
541 return;
542 }
543 }
544 }
545 }
546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 public void resetRestartCounter() {
548 restartCount = 0;
549 restartDelay = 0;
550 restartTime = 0;
551 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500552
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700553 public StartItem findDeliveredStart(int id, boolean remove) {
554 final int N = deliveredStarts.size();
555 for (int i=0; i<N; i++) {
556 StartItem si = deliveredStarts.get(i);
557 if (si.id == id) {
558 if (remove) deliveredStarts.remove(i);
559 return si;
560 }
561 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500562
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -0700563 return null;
564 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500565
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700566 public int getLastStartId() {
567 return lastStartId;
568 }
569
570 public int makeNextStartId() {
571 lastStartId++;
572 if (lastStartId < 1) {
573 lastStartId = 1;
574 }
575 return lastStartId;
576 }
577
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700578 public void postNotification() {
Daniel Sandlerd0a2f862010-08-03 15:29:31 -0400579 final int appUid = appInfo.uid;
580 final int appPid = app.pid;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700581 if (foregroundId != 0 && foregroundNoti != null) {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800582 // Do asynchronous communication with notification manager to
583 // avoid deadlocks.
584 final String localPackageName = packageName;
585 final int localForegroundId = foregroundId;
Dan Sandlerd63f9322015-05-06 15:18:49 -0400586 final Notification _foregroundNoti = foregroundNoti;
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800587 ams.mHandler.post(new Runnable() {
588 public void run() {
Adam Lesinski182f73f2013-12-05 16:48:06 -0800589 NotificationManagerInternal nm = LocalServices.getService(
590 NotificationManagerInternal.class);
Daniel Sandlerd0a2f862010-08-03 15:29:31 -0400591 if (nm == null) {
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800592 return;
593 }
Dan Sandlerd63f9322015-05-06 15:18:49 -0400594 Notification localForegroundNoti = _foregroundNoti;
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800595 try {
Dan Sandlerd63f9322015-05-06 15:18:49 -0400596 if (localForegroundNoti.getSmallIcon() == null) {
Wang Lee2c1f9b2016-05-04 19:24:35 +0800597 // It is not correct for the caller to not supply a notification
Dianne Hackborn2ced96c2013-03-21 14:23:46 -0700598 // icon, but this used to be able to slip through, so for
Dan Sandlerd63f9322015-05-06 15:18:49 -0400599 // those dirty apps we will create a notification clearly
600 // blaming the app.
Dan Sandler4e787062015-06-17 15:09:48 -0400601 Slog.v(TAG, "Attempted to start a foreground service ("
602 + name
603 + ") with a broken notification (no icon: "
604 + localForegroundNoti
605 + ")");
Daniel Sandler91fe8452013-04-08 12:23:27 -0400606
Daniel Sandler91fe8452013-04-08 12:23:27 -0400607 CharSequence appName = appInfo.loadLabel(
608 ams.mContext.getPackageManager());
609 if (appName == null) {
610 appName = appInfo.packageName;
611 }
612 Context ctx = null;
613 try {
Wang Lee2c1f9b2016-05-04 19:24:35 +0800614 ctx = ams.mContext.createPackageContextAsUser(
615 appInfo.packageName, 0, new UserHandle(userId));
Dan Sandlerd63f9322015-05-06 15:18:49 -0400616
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500617 Notification.Builder notiBuilder = new Notification.Builder(ctx,
Julia Reynoldsbad42972017-04-25 13:52:49 -0400618 localForegroundNoti.getChannelId());
Dan Sandlerd63f9322015-05-06 15:18:49 -0400619
620 // it's ugly, but it clearly identifies the app
621 notiBuilder.setSmallIcon(appInfo.icon);
622
Dan Sandler4e787062015-06-17 15:09:48 -0400623 // mark as foreground
624 notiBuilder.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true);
625
Daniel Sandler91fe8452013-04-08 12:23:27 -0400626 Intent runningIntent = new Intent(
627 Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
628 runningIntent.setData(Uri.fromParts("package",
629 appInfo.packageName, null));
luozhanwei279544c2017-04-05 13:30:53 +0800630 PendingIntent pi = PendingIntent.getActivityAsUser(ams.mContext, 0,
631 runningIntent, PendingIntent.FLAG_UPDATE_CURRENT, null,
632 UserHandle.of(userId));
Dan Sandlerd63f9322015-05-06 15:18:49 -0400633 notiBuilder.setColor(ams.mContext.getColor(
Selim Cinek255dd042014-08-19 22:29:02 +0200634 com.android.internal
Dan Sandlerd63f9322015-05-06 15:18:49 -0400635 .R.color.system_notification_accent_color));
636 notiBuilder.setContentTitle(
Daniel Sandler91fe8452013-04-08 12:23:27 -0400637 ams.mContext.getString(
638 com.android.internal.R.string
639 .app_running_notification_title,
Dan Sandlerd63f9322015-05-06 15:18:49 -0400640 appName));
641 notiBuilder.setContentText(
Daniel Sandler91fe8452013-04-08 12:23:27 -0400642 ams.mContext.getString(
643 com.android.internal.R.string
644 .app_running_notification_text,
Dan Sandlerd63f9322015-05-06 15:18:49 -0400645 appName));
646 notiBuilder.setContentIntent(pi);
647
648 localForegroundNoti = notiBuilder.build();
Daniel Sandler91fe8452013-04-08 12:23:27 -0400649 } catch (PackageManager.NameNotFoundException e) {
Dianne Hackborn2ced96c2013-03-21 14:23:46 -0700650 }
651 }
Julia Reynolds5a4399a2017-10-11 08:44:46 -0400652 if (nm.getNotificationChannel(localPackageName, appUid,
Julia Reynoldsf3de8aa2017-09-29 15:52:37 -0400653 localForegroundNoti.getChannelId()) == null) {
Julia Reynolds5a4399a2017-10-11 08:44:46 -0400654 int targetSdkVersion = Build.VERSION_CODES.O_MR1;
655 try {
656 final ApplicationInfo applicationInfo =
657 ams.mContext.getPackageManager().getApplicationInfoAsUser(
658 appInfo.packageName, 0, userId);
659 targetSdkVersion = applicationInfo.targetSdkVersion;
660 } catch (PackageManager.NameNotFoundException e) {
661 }
662 if (targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
663 throw new RuntimeException(
664 "invalid channel for service notification: "
665 + foregroundNoti);
666 }
667 }
668 if (localForegroundNoti.getSmallIcon() == null) {
Dianne Hackborn282add72013-03-15 18:48:04 -0700669 // Notifications whose icon is 0 are defined to not show
670 // a notification, silently ignoring it. We don't want to
671 // just ignore it, we want to prevent the service from
672 // being foreground.
Dan Sandlerd63f9322015-05-06 15:18:49 -0400673 throw new RuntimeException("invalid service notification: "
674 + foregroundNoti);
Dianne Hackborn282add72013-03-15 18:48:04 -0700675 }
Adam Lesinski182f73f2013-12-05 16:48:06 -0800676 nm.enqueueNotification(localPackageName, localPackageName,
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800677 appUid, appPid, null, localForegroundId, localForegroundNoti,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400678 userId);
Dan Sandler4e787062015-06-17 15:09:48 -0400679
680 foregroundNoti = localForegroundNoti; // save it for amending next time
Joe Onorato34fcf972010-02-18 07:45:17 -0500681 } catch (RuntimeException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800682 Slog.w(TAG, "Error showing notification for service", e);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800683 // If it gave us a garbage notification, it doesn't
684 // get to be foreground.
685 ams.setServiceForeground(name, ServiceRecord.this,
Dianne Hackborn67324c92016-04-18 13:55:25 -0700686 0, null, 0);
Christopher Tate8aa8fe12017-01-20 17:50:32 -0800687 ams.crashApplication(appUid, appPid, localPackageName, -1,
Joe Onoratoeaa07182010-09-23 16:49:20 -0700688 "Bad notification for startForeground: " + e);
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800689 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700690 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -0800691 });
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700692 }
693 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500694
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700695 public void cancelNotification() {
Dianne Hackborn0ba4c712016-08-01 17:49:41 -0700696 // Do asynchronous communication with notification manager to
697 // avoid deadlocks.
698 final String localPackageName = packageName;
699 final int localForegroundId = foregroundId;
700 ams.mHandler.post(new Runnable() {
701 public void run() {
702 INotificationManager inm = NotificationManager.getService();
703 if (inm == null) {
704 return;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700705 }
Dianne Hackborn0ba4c712016-08-01 17:49:41 -0700706 try {
707 inm.cancelNotificationWithTag(localPackageName, null,
708 localForegroundId, userId);
709 } catch (RuntimeException e) {
710 Slog.w(TAG, "Error canceling notification for service", e);
711 } catch (RemoteException e) {
712 }
713 }
714 });
Dianne Hackbornd8a43f62009-08-17 23:33:56 -0700715 }
Christoph Studer365e4c32014-09-18 20:35:36 +0200716
717 public void stripForegroundServiceFlagFromNotification() {
718 if (foregroundId == 0) {
719 return;
720 }
721
722 final int localForegroundId = foregroundId;
723 final int localUserId = userId;
724 final String localPackageName = packageName;
725
726 // Do asynchronous communication with notification manager to
727 // avoid deadlocks.
728 ams.mHandler.post(new Runnable() {
729 @Override
730 public void run() {
731 NotificationManagerInternal nmi = LocalServices.getService(
732 NotificationManagerInternal.class);
733 if (nmi == null) {
734 return;
735 }
736 nmi.removeForegroundServiceFlagFromNotification(localPackageName, localForegroundId,
737 localUserId);
738 }
739 });
740 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500741
Dianne Hackborn39792d22010-08-19 18:01:52 -0700742 public void clearDeliveredStartsLocked() {
743 for (int i=deliveredStarts.size()-1; i>=0; i--) {
744 deliveredStarts.get(i).removeUriPermissionsLocked();
745 }
746 deliveredStarts.clear();
747 }
748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700750 if (stringName != null) {
751 return stringName;
752 }
753 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700754 sb.append("ServiceRecord{")
755 .append(Integer.toHexString(System.identityHashCode(this)))
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700756 .append(" u").append(userId)
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700757 .append(' ').append(shortName).append('}');
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700758 return stringName = sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 }
760}