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

Commit 2d6196e4 authored by John Spurlock's avatar John Spurlock Committed by Android (Google) Code Review
Browse files

Merge "Add 'read' subcommand to the 'content' tool."

parents 9187e40b cee823e4
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -26,9 +26,17 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.text.TextUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import libcore.io.IoUtils;

/**
 * This class is a command line utility for manipulating content. A client
 * can insert, update, and remove records in a content provider. For example,
@@ -109,6 +117,12 @@ public class Content {
        + "  <METHOD> is the name of a provider-defined method\n"
        + "  <ARG> is an optional string argument\n"
        + "  <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n"
        + "\n"
        + "usage: adb shell content read --uri <URI> [--user <USER_ID>]\n"
        + "  Example:\n"
        + "  # cat default ringtone to a file, then pull to host\n"
        + "  adb shell 'content read --uri content://settings/system/ringtone >"
                + " /mnt/sdcard/tmp.ogg' && adb pull /mnt/sdcard/tmp.ogg\n"
        + "\n";

    private static class Parser {
@@ -117,6 +131,7 @@ public class Content {
        private static final String ARGUMENT_UPDATE = "update";
        private static final String ARGUMENT_QUERY = "query";
        private static final String ARGUMENT_CALL = "call";
        private static final String ARGUMENT_READ = "read";
        private static final String ARGUMENT_WHERE = "--where";
        private static final String ARGUMENT_BIND = "--bind";
        private static final String ARGUMENT_URI = "--uri";
@@ -154,6 +169,8 @@ public class Content {
                    return parseQueryCommand();
                } else if (ARGUMENT_CALL.equals(operation)) {
                    return parseCallCommand();
                } else if (ARGUMENT_READ.equals(operation)) {
                    return parseReadCommand();
                } else {
                    throw new IllegalArgumentException("Unsupported operation: " + operation);
                }
@@ -273,6 +290,25 @@ public class Content {
            return new CallCommand(uri, userId, method, arg, values);
        }

        private ReadCommand parseReadCommand() {
            Uri uri = null;
            int userId = UserHandle.USER_OWNER;
            for (String argument; (argument = mTokenizer.nextArg())!= null;) {
                if (ARGUMENT_URI.equals(argument)) {
                    uri = Uri.parse(argumentValueRequired(argument));
                } else if (ARGUMENT_USER.equals(argument)) {
                    userId = Integer.parseInt(argumentValueRequired(argument));
                } else {
                    throw new IllegalArgumentException("Unsupported argument: " + argument);
                }
            }
            if (uri == null) {
                throw new IllegalArgumentException("Content provider URI not specified."
                        + " Did you specify --uri argument?");
            }
            return new ReadCommand(uri, userId);
        }

        public QueryCommand parseQueryCommand() {
            Uri uri = null;
            int userId = UserHandle.USER_OWNER;
@@ -458,6 +494,31 @@ public class Content {
        }
    }

    private static class ReadCommand extends Command {
        public ReadCommand(Uri uri, int userId) {
            super(uri, userId);
        }

        @Override
        public void onExecute(IContentProvider provider) throws Exception {
            final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null);
            copy(new FileInputStream(fd.getFileDescriptor()), System.out);
        }

        private static void copy(InputStream is, OutputStream os) throws IOException {
            final byte[] buffer = new byte[8 * 1024];
            int read;
            try {
                while ((read = is.read(buffer)) > -1) {
                    os.write(buffer, 0, read);
                }
            } finally {
                IoUtils.closeQuietly(is);
                IoUtils.closeQuietly(os);
            }
        }
    }

    private static class QueryCommand extends DeleteCommand {
        final String[] mProjection;
        final String mSortOrder;