Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2ddee26 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by android-build-merger
Browse files

Merge "Fix issue #28641630: Service client dumps are timing out for no reason" into nyc-dev

am: 8f359afd

* commit '8f359afd':
  Fix issue #28641630: Service client dumps are timing out for no reason

Change-Id: I67af48d0e861e77e3bca389970aed1601567f2c7
parents 4d7e92b5 8f359afd
Loading
Loading
Loading
Loading
+313 −168
Original line number Diff line number Diff line
@@ -2805,28 +2805,63 @@ public final class ActiveServices {
    /**
     * Prints a list of ServiceRecords (dumpsys activity services)
     */
    void dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
        boolean needSep = false;
        boolean printedAnything = false;
    List<ServiceRecord> collectServicesToDumpLocked(ItemMatcher matcher, String dumpPackage) {
        final ArrayList<ServiceRecord> services = new ArrayList<>();
        final int[] users = mAm.mUserController.getUsers();
        for (int user : users) {
            ServiceMap smap = getServiceMap(user);
            if (smap.mServicesByName.size() > 0) {
                for (int si=0; si<smap.mServicesByName.size(); si++) {
                    ServiceRecord r = smap.mServicesByName.valueAt(si);
                    if (!matcher.match(r, r.name)) {
                        continue;
                    }
                    if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                        continue;
                    }
                    services.add(r);
                }
            }
        }

        ItemMatcher matcher = new ItemMatcher();
        return services;
    }

    final class ServiceDumper {
        private final FileDescriptor fd;
        private final PrintWriter pw;
        private final String[] args;
        private final int opti;
        private final boolean dumpAll;
        private final String dumpPackage;
        private final ItemMatcher matcher;
        private final ArrayList<ServiceRecord> services = new ArrayList<>();

        private final long nowReal = SystemClock.elapsedRealtime();

        private boolean needSep = false;
        private boolean printedAnything = false;
        private boolean printed = false;

        /**
         * Note: do not call directly, use {@link #newServiceDumperLocked} instead (this
         * must be called with the lock held).
         */
        ServiceDumper(FileDescriptor fd, PrintWriter pw, String[] args,
                int opti, boolean dumpAll, String dumpPackage) {
            this.fd = fd;
            this.pw = pw;
            this.args = args;
            this.opti = opti;
            this.dumpAll = dumpAll;
            this.dumpPackage = dumpPackage;
            matcher = new ItemMatcher();
            matcher.build(args, opti);

        pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
        try {
            if (mLastAnrDump != null) {
                pw.println("  Last ANR service:");
                pw.print(mLastAnrDump);
                pw.println();
            }
            int[] users = mAm.mUserController.getUsers();
            final int[] users = mAm.mUserController.getUsers();
            for (int user : users) {
                ServiceMap smap = getServiceMap(user);
                boolean printed = false;
                if (smap.mServicesByName.size() > 0) {
                    long nowReal = SystemClock.elapsedRealtime();
                    needSep = false;
                    for (int si=0; si<smap.mServicesByName.size(); si++) {
                        ServiceRecord r = smap.mServicesByName.valueAt(si);
                        if (!matcher.match(r, r.name)) {
@@ -2835,6 +2870,99 @@ public final class ActiveServices {
                        if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                            continue;
                        }
                        services.add(r);
                    }
                }
            }
        }

        private void dumpHeaderLocked() {
            pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
            if (mLastAnrDump != null) {
                pw.println("  Last ANR service:");
                pw.print(mLastAnrDump);
                pw.println();
            }
        }

        void dumpLocked() {
            dumpHeaderLocked();

            try {
                int[] users = mAm.mUserController.getUsers();
                for (int user : users) {
                    // Find the first service for this user.
                    int serviceIdx = 0;
                    while (serviceIdx < services.size() && services.get(serviceIdx).userId != user) {
                        serviceIdx++;
                    }
                    printed = false;
                    if (serviceIdx < services.size()) {
                        needSep = false;
                        while (serviceIdx < services.size()) {
                            ServiceRecord r = services.get(serviceIdx);
                            serviceIdx++;
                            if (r.userId != user) {
                                break;
                            }
                            dumpServiceLocalLocked(r);
                        }
                        needSep |= printed;
                    }

                    dumpUserRemainsLocked(user);
                }
            } catch (Exception e) {
                Slog.w(TAG, "Exception in dumpServicesLocked", e);
            }

            dumpRemainsLocked();
        }

        void dumpWithClient() {
            synchronized(mAm) {
                dumpHeaderLocked();
            }

            try {
                int[] users = mAm.mUserController.getUsers();
                for (int user : users) {
                    // Find the first service for this user.
                    int serviceIdx = 0;
                    while (serviceIdx < services.size() && services.get(serviceIdx).userId != user) {
                        serviceIdx++;
                    }
                    printed = false;
                    if (serviceIdx < services.size()) {
                        needSep = false;
                        while (serviceIdx < services.size()) {
                            ServiceRecord r = services.get(serviceIdx);
                            serviceIdx++;
                            if (r.userId != user) {
                                break;
                            }
                            synchronized(mAm) {
                                dumpServiceLocalLocked(r);
                            }
                            dumpServiceClient(r);
                        }
                        needSep |= printed;
                    }

                    synchronized(mAm) {
                        dumpUserRemainsLocked(user);
                    }
                }
            } catch (Exception e) {
                Slog.w(TAG, "Exception in dumpServicesLocked", e);
            }

            synchronized(mAm) {
                dumpRemainsLocked();
            }
        }

        private void dumpUserHeaderLocked(int user) {
            if (!printed) {
                if (printedAnything) {
                    pw.println();
@@ -2846,6 +2974,10 @@ public final class ActiveServices {
            if (needSep) {
                pw.println();
            }
        }

        private void dumpServiceLocalLocked(ServiceRecord r) {
            dumpUserHeaderLocked(r.userId);
            pw.print("  * ");
            pw.println(r);
            if (dumpAll) {
@@ -2876,14 +3008,23 @@ public final class ActiveServices {
                    }
                }
            }
                        if (dumpClient && r.app != null && r.app.thread != null) {
        }

        private void dumpServiceClient(ServiceRecord r) {
            final ProcessRecord proc = r.app;
            if (proc == null) {
                return;
            }
            final IApplicationThread thread = proc.thread;
            if (thread == null) {
                return;
            }
            pw.println("    Client:");
            pw.flush();
            try {
                TransferPipe tp = new TransferPipe();
                try {
                                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
                                            r, args);
                    thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
                    tp.setBufferPrefix("      ");
                    // Short timeout, since blocking here can
                    // deadlock with the application.
@@ -2898,9 +3039,9 @@ public final class ActiveServices {
            }
            needSep = true;
        }
                    }
                    needSep |= printed;
                }

        private void dumpUserRemainsLocked(int user) {
            ServiceMap smap = getServiceMap(user);
            printed = false;
            for (int si=0, SN=smap.mDelayedStartList.size(); si<SN; si++) {
                ServiceRecord r = smap.mDelayedStartList.get(si);
@@ -2940,12 +3081,10 @@ public final class ActiveServices {
                pw.print("  * Starting bg "); pw.println(r);
            }
        }
        } catch (Exception e) {
            Slog.w(TAG, "Exception in dumpServicesLocked", e);
        }

        private void dumpRemainsLocked() {
            if (mPendingServices.size() > 0) {
            boolean printed = false;
                printed = false;
                for (int i=0; i<mPendingServices.size(); i++) {
                    ServiceRecord r = mPendingServices.get(i);
                    if (!matcher.match(r, r.name)) {
@@ -2968,7 +3107,7 @@ public final class ActiveServices {
            }

            if (mRestartingServices.size() > 0) {
            boolean printed = false;
                printed = false;
                for (int i=0; i<mRestartingServices.size(); i++) {
                    ServiceRecord r = mRestartingServices.get(i);
                    if (!matcher.match(r, r.name)) {
@@ -2991,7 +3130,7 @@ public final class ActiveServices {
            }

            if (mDestroyingServices.size() > 0) {
            boolean printed = false;
                printed = false;
                for (int i=0; i< mDestroyingServices.size(); i++) {
                    ServiceRecord r = mDestroyingServices.get(i);
                    if (!matcher.match(r, r.name)) {
@@ -3014,7 +3153,7 @@ public final class ActiveServices {
            }

            if (dumpAll) {
            boolean printed = false;
                printed = false;
                for (int ic=0; ic<mServiceConnections.size(); ic++) {
                    ArrayList<ConnectionRecord> r = mServiceConnections.valueAt(ic);
                    for (int i=0; i<r.size(); i++) {
@@ -3043,6 +3182,12 @@ public final class ActiveServices {
                pw.println("  (nothing)");
            }
        }
    }

    ServiceDumper newServiceDumperLocked(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean dumpAll, String dumpPackage) {
        return new ServiceDumper(fd, pw, args, opti, dumpAll, dumpPackage);
    }

    /**
     * There are three ways to call this:
+105 −40
Original line number Diff line number Diff line
@@ -13804,8 +13804,18 @@ public final class ActivityManagerService extends ActivityManagerNative
                    dumpAssociationsLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
                }
            } else if ("services".equals(cmd) || "s".equals(cmd)) {
                if (dumpClient) {
                    ActiveServices.ServiceDumper dumper;
                    synchronized (this) {
                    mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
                        dumper = mServices.newServiceDumperLocked(fd, pw, args, opti, true,
                                dumpPackage);
                    }
                    dumper.dumpWithClient();
                } else {
                    synchronized (this) {
                        mServices.newServiceDumperLocked(fd, pw, args, opti, true,
                                dumpPackage).dumpLocked();
                    }
                }
            } else if ("locks".equals(cmd)) {
                LockGuard.dump(fd, pw, args);
@@ -13827,6 +13837,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        // No piece of data specified, dump everything.
        if (dumpClient) {
            ActiveServices.ServiceDumper sdumper;
            synchronized (this) {
                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
@@ -13848,8 +13860,12 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
            mServices.dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
                sdumper = mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll,
                        dumpPackage);
            }
            sdumper.dumpWithClient();
            pw.println();
            synchronized (this) {
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
@@ -13872,6 +13888,55 @@ public final class ActivityManagerService extends ActivityManagerNative
                }
                dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
            }
        } else {
            synchronized (this) {
                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpPermissionsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll, dumpPackage)
                        .dumpLocked();
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
                if (mAssociations.size() > 0) {
                    pw.println();
                    if (dumpAll) {
                        pw.println("-------------------------------------------------------------------------------");
                    }
                    dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
                }
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }
@@ -16175,8 +16240,8 @@ public final class ActivityManagerService extends ActivityManagerNative
            catPw.println();
            dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
            catPw.println();
            mServices.dumpServicesLocked(null, catPw, emptyArgs, 0,
                    false, false, null);
            mServices.newServiceDumperLocked(null, catPw, emptyArgs, 0,
                    false, null).dumpLocked();
            catPw.println();
            dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
            catPw.flush();