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