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