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

Commit 26cdf931 authored by Stefan Andonian's avatar Stefan Andonian
Browse files

Fix "Hanging Final Read" bug for ViewCapture data transfers.

Bug: 224595733
Test: Verified this works manually on device.
Change-Id: I08fceb69073b931c27f50ec4d9d0ace7c5de8b4a
parent f2a089d3
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -107,19 +107,22 @@ import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.SizedInputStream;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.wm.ActivityTaskManagerInternal;

import java.io.DataInputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Arrays;
@@ -1512,7 +1515,7 @@ public class LauncherAppsService extends SystemService {
                    forEachViewCaptureWindow((fileName, is) -> {
                        try {
                            zipOs.putNextEntry(new ZipEntry("FS" + fileName));
                            is.transferTo(zipOs);
                            transferViewCaptureData(is, zipOs);
                            zipOs.closeEntry();
                        } catch (IOException e) {
                            getErrPrintWriter().write("Failed to output " + fileName
@@ -1553,14 +1556,24 @@ public class LauncherAppsService extends SystemService {
        private void dumpViewCaptureDataToWmTrace(@NonNull String fileName,
                @NonNull InputStream is) {
            Path outPath = Paths.get(fileName);
            try {
                Files.copy(is, outPath, StandardCopyOption.REPLACE_EXISTING);
            try (OutputStream os = Files.newOutputStream(outPath, StandardOpenOption.CREATE,
                    StandardOpenOption.TRUNCATE_EXISTING)) {
                transferViewCaptureData(is, os);
                Files.setPosixFilePermissions(outPath, WM_TRACE_FILE_PERMISSIONS);
            } catch (IOException e) {
                Log.d(TAG, "failed to write data to " + fileName + " in wmtrace dir", e);
            }
        }

        /**
         * Raw input stream reads hang on the final read when transferring data in via the pipe.
         * The fix used below is to count and read the exact amount of bytes being sent.
         */
        private void transferViewCaptureData(InputStream is, OutputStream os) throws IOException {
            DataInputStream dataInputStream = new DataInputStream(is);
            new SizedInputStream(dataInputStream, dataInputStream.readInt()).transferTo(os);
        }

        /**
         * IDumpCallback.onDump alerts the in-process ViewCapture instance to start sending data
         * to LauncherAppsService via the pipe's input provided. This data (as well as an output