Example usage for android.os IBinder dumpAsync

List of usage examples for android.os IBinder dumpAsync

Introduction

In this page you can find the example usage for android.os IBinder dumpAsync.

Prototype

public void dumpAsync(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException;

Source Link

Document

Like #dump(FileDescriptor,String[]) but always executes asynchronously.

Usage

From source file:com.github.michalbednarski.intentslab.Utils.java

@TargetApi(13) // Function handles all supported api levels
public static InputStream dumpSystemService(Context context, String serviceName, final String[] arguments)
        throws Exception {
    // Check if we have permission to invoke dump from our process
    final boolean canDumpLocally = context.getPackageManager().checkPermission(android.Manifest.permission.DUMP,
            context.getPackageName()) == PackageManager.PERMISSION_GRANTED;

    // On versions without createPipe() just execute dumpsys
    if (android.os.Build.VERSION.SDK_INT < 9) {
        if (!canDumpLocally) {
            throw new Exception("Dumping is not supported on this system version");
        }//  www  .  ja  v a 2s  .  c  om
        String[] progArray = new String[arguments != null ? 2 + arguments.length : 2];
        progArray[0] = "dumpsys";
        progArray[1] = serviceName;
        if (arguments != null) {
            System.arraycopy(arguments, 0, progArray, 2, arguments.length);
        }
        return Runtime.getRuntime().exec(progArray).getInputStream();
    }

    // Get service
    final Class<?> serviceManager = Class.forName("android.os.ServiceManager");
    final IBinder service = (IBinder) serviceManager.getMethod("getService", String.class).invoke(null,
            serviceName);

    // Check permissions and get remote interface if needed
    IRemoteInterface remoteInterface = null;
    if (!canDumpLocally) {
        remoteInterface = RunAsManager.getRemoteInterfaceForSystemDebuggingCommands();
        if (remoteInterface == null) {
            throw new SecurityException("Process has no permission to dump services");
        }
    }

    // Create pipe, write(pipe[0]) -> read(pipe[1])
    final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
    final ParcelFileDescriptor readablePipe = pipe[0];
    final ParcelFileDescriptor writablePipe = pipe[1];

    try {
        // Execute dump
        if (canDumpLocally) {
            if (android.os.Build.VERSION.SDK_INT >= 13) {
                service.dumpAsync(writablePipe.getFileDescriptor(), arguments);
                writablePipe.close();
            } else {
                (new Thread() {
                    @Override
                    public void run() {
                        try {
                            service.dump(writablePipe.getFileDescriptor(), arguments);
                            writablePipe.close();
                        } catch (Exception e) {
                            // TODO: can we handle this?
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        } else {
            remoteInterface.dumpServiceAsync(service, writablePipe, arguments);
            writablePipe.close();
        }
        // If anything went wrong, close pipe and rethrow
    } catch (Throwable e) {
        readablePipe.close();
        writablePipe.close();
        throwUnchecked(e);
        throw new Error(); // Unreachable
    }

    // Return stream that will ensure closing fd
    return new FileInputStream(readablePipe.getFileDescriptor()) {
        @Override
        public void close() throws IOException {
            super.close();
            readablePipe.close();
        }
    };
}