OSDN Git Service

Merge "AAPT2: Ensure strings are sorted by configuration" into oc-mr1-dev
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / ServiceRecord.java
index 87cb40e..16995e5 100644 (file)
@@ -16,7 +16,7 @@
 
 package com.android.server.am;
 
-import com.android.internal.app.ProcessStats;
+import com.android.internal.app.procstats.ServiceState;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.LocalServices;
 import com.android.server.notification.NotificationManagerInternal;
@@ -33,6 +33,7 @@ import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -88,9 +89,12 @@ final class ServiceRecord extends Binder {
 
     ProcessRecord app;      // where this service is running or null.
     ProcessRecord isolatedProc; // keep track of isolated process, if requested
-    ProcessStats.ServiceState tracker; // tracking service execution, may be null
-    ProcessStats.ServiceState restartTracker; // tracking service restart
+    ServiceState tracker; // tracking service execution, may be null
+    ServiceState restartTracker; // tracking service restart
+    boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
     boolean delayed;        // are we waiting to start this service in the background?
+    boolean fgRequired;     // is the service required to go foreground after starting?
+    boolean fgWaiting;      // is a timeout for going foreground already scheduled?
     boolean isForeground;   // is service currently in foreground mode?
     int foregroundId;       // Notification ID of last foreground req.
     Notification foregroundNoti; // Notification record of foreground state.
@@ -114,13 +118,14 @@ final class ServiceRecord extends Binder {
     long destroyTime;       // time at which destory was initiated.
 
     String stringName;      // caching of toString
-    
+
     private int lastStartId;    // identifier of most recent start request.
 
     static class StartItem {
         final ServiceRecord sr;
         final boolean taskRemoved;
         final int id;
+        final int callingId;
         final Intent intent;
         final ActivityManagerService.NeededUriGrants neededGrants;
         long deliveredTime;
@@ -131,12 +136,13 @@ final class ServiceRecord extends Binder {
         String stringName;      // caching of toString
 
         StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent,
-                ActivityManagerService.NeededUriGrants _neededGrants) {
+                ActivityManagerService.NeededUriGrants _neededGrants, int _callingId) {
             sr = _sr;
             taskRemoved = _taskRemoved;
             id = _id;
             intent = _intent;
             neededGrants = _neededGrants;
+            callingId = _callingId;
         }
 
         UriPermissionOwner getUriPermissionsLocked() {
@@ -202,7 +208,7 @@ final class ServiceRecord extends Binder {
             }
         }
     }
-    
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("intent={");
                 pw.print(intent.getIntent().toShortString(false, true, false, true));
@@ -225,6 +231,9 @@ final class ServiceRecord extends Binder {
         if (isolatedProc != null) {
             pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
         }
+        if (whitelistManager) {
+            pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
+        }
         if (delayed) {
             pw.print(prefix); pw.print("delayed="); pw.println(delayed);
         }
@@ -326,7 +335,7 @@ final class ServiceRecord extends Binder {
         createdFromFg = callerIsFg;
     }
 
-    public ProcessStats.ServiceState getTracker() {
+    public ServiceState getTracker() {
         if (tracker != null) {
             return tracker;
         }
@@ -391,12 +400,25 @@ final class ServiceRecord extends Binder {
         return false;
     }
 
+    public void updateWhitelistManager() {
+        whitelistManager = false;
+        for (int conni=connections.size()-1; conni>=0; conni--) {
+            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+            for (int i=0; i<cr.size(); i++) {
+                if ((cr.get(i).flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
+                    whitelistManager = true;
+                    return;
+                }
+            }
+        }
+    }
+
     public void resetRestartCounter() {
         restartCount = 0;
         restartDelay = 0;
         restartTime = 0;
     }
-    
+
     public StartItem findDeliveredStart(int id, boolean remove) {
         final int N = deliveredStarts.size();
         for (int i=0; i<N; i++) {
@@ -406,10 +428,10 @@ final class ServiceRecord extends Binder {
                 return si;
             }
         }
-        
+
         return null;
     }
-    
+
     public int getLastStartId() {
         return lastStartId;
     }
@@ -441,7 +463,7 @@ final class ServiceRecord extends Binder {
                     Notification localForegroundNoti = _foregroundNoti;
                     try {
                         if (localForegroundNoti.getSmallIcon() == null) {
-                            // It is not correct for the caller to supply a notification
+                            // It is not correct for the caller to not supply a notification
                             // icon, but this used to be able to slip through, so for
                             // those dirty apps we will create a notification clearly
                             // blaming the app.
@@ -458,10 +480,11 @@ final class ServiceRecord extends Binder {
                             }
                             Context ctx = null;
                             try {
-                                ctx = ams.mContext.createPackageContext(
-                                        appInfo.packageName, 0);
+                                ctx = ams.mContext.createPackageContextAsUser(
+                                        appInfo.packageName, 0, new UserHandle(userId));
 
-                                Notification.Builder notiBuilder = new Notification.Builder(ctx);
+                                Notification.Builder notiBuilder = new Notification.Builder(ctx,
+                                        localForegroundNoti.getChannelId());
 
                                 // it's ugly, but it clearly identifies the app
                                 notiBuilder.setSmallIcon(appInfo.icon);
@@ -469,15 +492,13 @@ final class ServiceRecord extends Binder {
                                 // mark as foreground
                                 notiBuilder.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true);
 
-                                // we are doing the app a kindness here
-                                notiBuilder.setPriority(Notification.PRIORITY_MIN);
-
                                 Intent runningIntent = new Intent(
                                         Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                 runningIntent.setData(Uri.fromParts("package",
                                         appInfo.packageName, null));
-                                PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
-                                        runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+                                PendingIntent pi = PendingIntent.getActivityAsUser(ams.mContext, 0,
+                                        runningIntent, PendingIntent.FLAG_UPDATE_CURRENT, null,
+                                        UserHandle.of(userId));
                                 notiBuilder.setColor(ams.mContext.getColor(
                                         com.android.internal
                                                 .R.color.system_notification_accent_color));
@@ -497,6 +518,22 @@ final class ServiceRecord extends Binder {
                             } catch (PackageManager.NameNotFoundException e) {
                             }
                         }
+                        if (nm.getNotificationChannel(localPackageName, appUid,
+                                localForegroundNoti.getChannelId()) == null) {
+                            int targetSdkVersion = Build.VERSION_CODES.O_MR1;
+                            try {
+                                final ApplicationInfo applicationInfo =
+                                        ams.mContext.getPackageManager().getApplicationInfoAsUser(
+                                                appInfo.packageName, 0, userId);
+                                targetSdkVersion = applicationInfo.targetSdkVersion;
+                            } catch (PackageManager.NameNotFoundException e) {
+                            }
+                            if (targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
+                                throw new RuntimeException(
+                                        "invalid channel for service notification: "
+                                                + foregroundNoti);
+                            }
+                        }
                         if (localForegroundNoti.getSmallIcon() == null) {
                             // Notifications whose icon is 0 are defined to not show
                             // a notification, silently ignoring it.  We don't want to
@@ -505,10 +542,9 @@ final class ServiceRecord extends Binder {
                             throw new RuntimeException("invalid service notification: "
                                     + foregroundNoti);
                         }
-                        int[] outId = new int[1];
                         nm.enqueueNotification(localPackageName, localPackageName,
                                 appUid, appPid, null, localForegroundId, localForegroundNoti,
-                                outId, userId);
+                                userId);
 
                         foregroundNoti = localForegroundNoti; // save it for amending next time
                     } catch (RuntimeException e) {
@@ -516,37 +552,35 @@ final class ServiceRecord extends Binder {
                         // If it gave us a garbage notification, it doesn't
                         // get to be foreground.
                         ams.setServiceForeground(name, ServiceRecord.this,
-                                0, null, true);
-                        ams.crashApplication(appUid, appPid, localPackageName,
+                                0, null, 0);
+                        ams.crashApplication(appUid, appPid, localPackageName, -1,
                                 "Bad notification for startForeground: " + e);
                     }
                 }
             });
         }
     }
-    
+
     public void cancelNotification() {
-        if (foregroundId != 0) {
-            // Do asynchronous communication with notification manager to
-            // avoid deadlocks.
-            final String localPackageName = packageName;
-            final int localForegroundId = foregroundId;
-            ams.mHandler.post(new Runnable() {
-                public void run() {
-                    INotificationManager inm = NotificationManager.getService();
-                    if (inm == null) {
-                        return;
-                    }
-                    try {
-                        inm.cancelNotificationWithTag(localPackageName, null,
-                                localForegroundId, userId);
-                    } catch (RuntimeException e) {
-                        Slog.w(TAG, "Error canceling notification for service", e);
-                    } catch (RemoteException e) {
-                    }
+        // Do asynchronous communication with notification manager to
+        // avoid deadlocks.
+        final String localPackageName = packageName;
+        final int localForegroundId = foregroundId;
+        ams.mHandler.post(new Runnable() {
+            public void run() {
+                INotificationManager inm = NotificationManager.getService();
+                if (inm == null) {
+                    return;
                 }
-            });
-        }
+                try {
+                    inm.cancelNotificationWithTag(localPackageName, null,
+                            localForegroundId, userId);
+                } catch (RuntimeException e) {
+                    Slog.w(TAG, "Error canceling notification for service", e);
+                } catch (RemoteException e) {
+                }
+            }
+        });
     }
 
     public void stripForegroundServiceFlagFromNotification() {
@@ -573,7 +607,7 @@ final class ServiceRecord extends Binder {
             }
         });
     }
-    
+
     public void clearDeliveredStartsLocked() {
         for (int i=deliveredStarts.size()-1; i>=0; i--) {
             deliveredStarts.get(i).removeUriPermissionsLocked();