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

Commit 4b89d63b authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Don't dump print state while holding lock

This causes ANRs as we are trying to the the print spooler connection
while holding a lock that can also be aquired on the system server's
main thread.

Fixes: 63159459
Test: cts-tradefed run singleCommand cts-dev -m Print
      adb shell dumpsys print
      incident_report print
Change-Id: I228fc5ddc10c1c89f61e8a6d8eb8ea9e384197a8
parent 9f5e9915
Loading
Loading
Loading
Loading
+27 −28
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import com.android.server.SystemService;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@@ -645,7 +646,6 @@ public final class PrintManagerService extends SystemService {

            int opti = 0;
            boolean dumpAsProto = false;
            int user = UserHandle.USER_ALL;
            while (opti < args.length) {
                String opt = args[opti];
                if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
@@ -659,50 +659,49 @@ public final class PrintManagerService extends SystemService {
                }
            }

            ArrayList<UserState> userStatesToDump = new ArrayList<>();
            synchronized (mLock) {
                int numUserStates = mUserStates.size();
                for (int i = 0; i < numUserStates; i++) {
                    userStatesToDump.add(mUserStates.valueAt(i));
                }
            }

            final long identity = Binder.clearCallingIdentity();
            try {
                if (dumpAsProto) {
                        dumpLocked(new ProtoOutputStream(fd), UserHandle.of(user));
                    dump(new ProtoOutputStream(fd), userStatesToDump);
                } else {
                        dumpLocked(fd, pw, UserHandle.of(user));
                    dump(fd, pw, userStatesToDump);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
        }

        private void dumpLocked(@NonNull ProtoOutputStream proto, @NonNull UserHandle user) {
            final int userStateCount = mUserStates.size();
        private void dump(@NonNull ProtoOutputStream proto,
                @NonNull ArrayList<UserState> userStatesToDump) {
            final int userStateCount = userStatesToDump.size();
            for (int i = 0; i < userStateCount; i++) {
                UserState userState = mUserStates.valueAt(i);

                if (user.equals(UserHandle.ALL) || mUserStates.keyAt(i) == user.getIdentifier()) {
                long token = proto.start(PrintServiceDumpProto.USER_STATES);
                    userState.dump(proto);
                userStatesToDump.get(i).dump(proto);
                proto.end(token);
            }
            }

            proto.flush();
        }

        private void dumpLocked(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
                @NonNull UserHandle user) {
        private void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
                @NonNull ArrayList<UserState> userStatesToDump) {
            pw = Preconditions.checkNotNull(pw);

            pw.println("PRINT MANAGER STATE (dumpsys print)");
            final int userStateCount = mUserStates.size();
            final int userStateCount = userStatesToDump.size();
            for (int i = 0; i < userStateCount; i++) {
                UserState userState = mUserStates.valueAt(i);

                if (user.equals(UserHandle.ALL) || mUserStates.keyAt(i) == user.getIdentifier()) {
                    userState.dump(fd, pw, "");
                userStatesToDump.get(i).dump(fd, pw, "");
                pw.println();
            }
        }
        }

        private void registerContentObservers() {
            final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(