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

Commit 398e49c8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Avoid loading the full file to memory in ConfigUpdateInstallReceiver"

parents 931bbaab 8b1ce905
Loading
Loading
Loading
Loading
+18 −11
Original line number Original line Diff line number Diff line
@@ -16,25 +16,30 @@


package com.android.server.updates;
package com.android.server.updates;


import com.android.internal.util.HexDump;
import android.os.FileUtils;
import android.os.FileUtils;
import android.system.Os;
import android.system.ErrnoException;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Base64;
import android.util.Base64;
import android.util.Slog;
import android.util.Slog;

import com.android.internal.util.HexDump;

import libcore.io.Streams;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.File;
import java.io.FileFilter;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.OutputStreamWriter;
import java.io.StringBufferInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchAlgorithmException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInstallReceiver {
public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInstallReceiver {


@@ -46,14 +51,13 @@ public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInsta
    }
    }


    @Override
    @Override
    protected void install(byte[] content, int version) throws IOException {
    protected void install(InputStream inputStream, int version) throws IOException {
        /* Install is complicated here because we translate the input, which is a JSON file
        /* Install is complicated here because we translate the input, which is a JSON file
         * containing log information to a directory with a file per log. To support atomically
         * containing log information to a directory with a file per log. To support atomically
         * replacing the old configuration directory with the new there's a bunch of steps. We
         * replacing the old configuration directory with the new there's a bunch of steps. We
         * create a new directory with the logs and then do an atomic update of the current symlink
         * create a new directory with the logs and then do an atomic update of the current symlink
         * to point to the new directory.
         * to point to the new directory.
         */
         */

        // 1. Ensure that the update dir exists and is readable
        // 1. Ensure that the update dir exists and is readable
        updateDir.mkdir();
        updateDir.mkdir();
        if (!updateDir.isDirectory()) {
        if (!updateDir.isDirectory()) {
@@ -72,7 +76,8 @@ public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInsta
            // and so we cannot delete the directory since its in use. Instead just bump the version
            // and so we cannot delete the directory since its in use. Instead just bump the version
            // and return.
            // and return.
            if (newVersion.getCanonicalPath().equals(currentSymlink.getCanonicalPath())) {
            if (newVersion.getCanonicalPath().equals(currentSymlink.getCanonicalPath())) {
                writeUpdate(updateDir, updateVersion, Long.toString(version).getBytes());
                writeUpdate(updateDir, updateVersion,
                        new ByteArrayInputStream(Long.toString(version).getBytes()));
                deleteOldLogDirectories();
                deleteOldLogDirectories();
                return;
                return;
            } else {
            } else {
@@ -92,6 +97,7 @@ public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInsta


            // 4. For each log in the log file create the corresponding file in <new_version>/ .
            // 4. For each log in the log file create the corresponding file in <new_version>/ .
            try {
            try {
                byte[] content = Streams.readFullyNoClose(inputStream);
                JSONObject json = new JSONObject(new String(content, StandardCharsets.UTF_8));
                JSONObject json = new JSONObject(new String(content, StandardCharsets.UTF_8));
                JSONArray logs = json.getJSONArray("logs");
                JSONArray logs = json.getJSONArray("logs");
                for (int i = 0; i < logs.length(); i++) {
                for (int i = 0; i < logs.length(); i++) {
@@ -119,7 +125,8 @@ public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInsta
        }
        }
        Slog.i(TAG, "CT log directory updated to " + newVersion.getAbsolutePath());
        Slog.i(TAG, "CT log directory updated to " + newVersion.getAbsolutePath());
        // 7. Update the current version information
        // 7. Update the current version information
        writeUpdate(updateDir, updateVersion, Long.toString(version).getBytes());
        writeUpdate(updateDir, updateVersion,
                new ByteArrayInputStream(Long.toString(version).getBytes()));
        // 8. Cleanup
        // 8. Cleanup
        deleteOldLogDirectories();
        deleteOldLogDirectories();
    }
    }
+20 −22
Original line number Original line Diff line number Diff line
@@ -16,9 +16,6 @@


package com.android.server.updates;
package com.android.server.updates;


import com.android.server.EventLogTags;
import com.android.internal.util.HexDump;

import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
@@ -26,6 +23,14 @@ import android.net.Uri;
import android.util.EventLog;
import android.util.EventLog;
import android.util.Slog;
import android.util.Slog;


import com.android.internal.util.HexDump;
import com.android.server.EventLogTags;

import libcore.io.IoUtils;
import libcore.io.Streams;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.IOException;
@@ -33,9 +38,6 @@ import java.io.InputStream;
import java.security.MessageDigest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchAlgorithmException;


import libcore.io.IoUtils;
import libcore.io.Streams;

public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
public class ConfigUpdateInstallReceiver extends BroadcastReceiver {


    private static final String TAG = "ConfigUpdateInstallReceiver";
    private static final String TAG = "ConfigUpdateInstallReceiver";
@@ -61,8 +63,6 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
            @Override
            @Override
            public void run() {
            public void run() {
                try {
                try {
                    // get the content path from the extras
                    byte[] altContent = getAltContent(context, intent);
                    // get the version from the extras
                    // get the version from the extras
                    int altVersion = getVersionFromIntent(intent);
                    int altVersion = getVersionFromIntent(intent);
                    // get the previous value from the extras
                    // get the previous value from the extras
@@ -79,7 +79,9 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
                    } else {
                    } else {
                        // install the new content
                        // install the new content
                        Slog.i(TAG, "Found new update, installing...");
                        Slog.i(TAG, "Found new update, installing...");
                        try (BufferedInputStream altContent = getAltContent(context, intent)) {
                            install(altContent, altVersion);
                            install(altContent, altVersion);
                        }
                        Slog.i(TAG, "Installation successful");
                        Slog.i(TAG, "Installation successful");
                        postInstall(context, intent);
                        postInstall(context, intent);
                    }
                    }
@@ -130,14 +132,9 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
        }
        }
    }
    }


    private byte[] getAltContent(Context c, Intent i) throws IOException {
    private BufferedInputStream getAltContent(Context c, Intent i) throws IOException {
        Uri content = getContentFromIntent(i);
        Uri content = getContentFromIntent(i);
        InputStream is = c.getContentResolver().openInputStream(content);
        return new BufferedInputStream(c.getContentResolver().openInputStream(content));
        try {
            return Streams.readFullyNoClose(is);
        } finally {
            is.close();
        }
    }
    }


    private byte[] getCurrentContent() {
    private byte[] getCurrentContent() {
@@ -175,7 +172,7 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
        return current.equals(required);
        return current.equals(required);
    }
    }


    protected void writeUpdate(File dir, File file, byte[] content) throws IOException {
    protected void writeUpdate(File dir, File file, InputStream inputStream) throws IOException {
        FileOutputStream out = null;
        FileOutputStream out = null;
        File tmp = null;
        File tmp = null;
        try {
        try {
@@ -192,7 +189,7 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
            tmp.setReadable(true, false);
            tmp.setReadable(true, false);
            // write to it
            // write to it
            out = new FileOutputStream(tmp);
            out = new FileOutputStream(tmp);
            out.write(content);
            Streams.copy(inputStream, out);
            // sync to disk
            // sync to disk
            out.getFD().sync();
            out.getFD().sync();
            // atomic rename
            // atomic rename
@@ -207,9 +204,10 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
        }
        }
    }
    }


    protected void install(byte[] content, int version) throws IOException {
    protected void install(InputStream inputStream, int version) throws IOException {
        writeUpdate(updateDir, updateContent, content);
        writeUpdate(updateDir, updateContent, inputStream);
        writeUpdate(updateDir, updateVersion, Long.toString(version).getBytes());
        writeUpdate(updateDir, updateVersion,
                new ByteArrayInputStream(Long.toString(version).getBytes()));
    }
    }


    protected void postInstall(Context context, Intent intent) {
    protected void postInstall(Context context, Intent intent) {