Android Open Source - PlayMusicExporter Super User Command






From Project

Back to project page PlayMusicExporter.

License

The source code is released under:

Copyright (c) 2015 David Schulte Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Soft...

If you think the Android project PlayMusicExporter listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (c) 2015 David Schulte// www.j  av  a  2 s . c  o  m
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package de.arcus.framework.superuser;

import android.app.Activity;

import org.apache.http.util.ByteArrayBuffer;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import de.arcus.framework.logger.Logger;

/**
 * This class executes superuser commands.
 */
public class SuperUserCommand {
    /**
     * The default timeout for each command in milliseconds
     */
    private static final long DEFAULT_COMMAND_TIMEOUT = 30 * 1000; // 30 seconds

    private String[] mCommands = new String[] {};
    private String[] mOutputStandard = new String[] {};
    private String[] mOutputError = new String[] {};

    // If we want to get a binary return
    private byte[] mOutputStandardBinary = new byte[] {};

    /**
     * Command failed?
     */
    private boolean mSuperUserFailed;

    /**
     * If this value is set, the command will not store any input to the logger
     */
    private boolean mHideInput = false;
    /**
     * If this value is set, the command will not store any standard output to the logger
     */
    private boolean mHideStandardOutput = false;
    /**
     * If this value is set, the command will not store any error output to the logger
     */
    private boolean mHideErrorOutput = false;

    /**
     * @return Gets whether the command hides the input log
     */
    public boolean getHideInput() {
        return mHideInput;
    }

    /**
     * @param hideInput Set this to hide the input to the logger
     */
    public void setHideInput(boolean hideInput) {
        mHideInput = hideInput;
    }

    /**
     * @return Gets whether the command hides the standard output log
     */
    public boolean getHideStandardOutput() {
        return mHideStandardOutput;
    }

    /**
     * @param hideStandardOutput Set this to hide the standard output to the logger
     */
    public void setHideStandardOutput(boolean hideStandardOutput) {
        mHideStandardOutput = hideStandardOutput;
    }

    /**
     * @return Gets whether the command hides the error output log
     */
    public boolean getHideErrorOutput() {
        return mHideErrorOutput;
    }

    /**
     * @param hideErrorOutput Set this to hide the error output to the logger
     */
    public void setHideErrorOutput(boolean hideErrorOutput) {
        mHideErrorOutput = hideErrorOutput;
    }

    /**
     * If this value is set the command will read the standard output as binary
     */
    private boolean mBinaryStandardOutput = false;

    /**
     * @return Gets whether the output will be binary
     */
    public boolean getBinaryStandardOutput() {
        return mBinaryStandardOutput;
    }

    /**
     * @param binaryStandardOutput Set this if you want a binary output
     */
    public void setBinaryStandardOutput(boolean binaryStandardOutput) {
        mBinaryStandardOutput = binaryStandardOutput;
    }

    /**
     * The timeout for this command in milliseconds
     */
    private long mTimeout;

    /**
     * @return Gets the timeout for this command in milliseconds
     */
    public long getTimeout() {
        return mTimeout;
    }

    /**
     * Set the timeout for this command in milliseconds
     * @param timeout Timeout
     * @return Itself
     */
    public SuperUserCommand setTimeout(long timeout) {
        mTimeout = timeout;
        return this;
    }

    /**
     * @return Gets the executed commands
     */
    public String[] getCommands() {
        return mCommands;
    }

    /**
     * @return Gets the standard output
     */
    public String[] getStandardOutput() {
        return mOutputStandard;
    }

    /**
     * @return Gets the error output
     */
    public String[] getErrorOutput() {
        return mOutputError;
    }

    /**
     * @return Gets the standard output as binary
     */
    public byte[] getStandardOutputBinary() {
        return mOutputStandardBinary;
    }

    /**
     * @return Gets whether the command was executed without errors, even without error outputs from the command.
     */
    public boolean commandWasSuccessful() {
        return (!mSuperUserFailed && mOutputError.length == 0);
    }

    /**
     * @return Gets whether the command was granted superuser permissions, but maybe has some error outputs.
     */
    public boolean superuserWasSuccessful() {
        return (!mSuperUserFailed);
    }

    /**
     * The async execution thread
     */
    private SuperUserCommandThread mThread;

    /**
     * The async callback
     */
    private SuperUserCommandCallback mCallback;

    /**
     * Creates a command with one command line
     * @param command The command
     */
    public SuperUserCommand(String command) {
        this(new String[] {command});
    }

    /**
     * Creates a command with multiple command lines
     * @param commands The command lines
     */
    public SuperUserCommand(String[] commands) {
        mCommands = commands;

        // Default timeout
        mTimeout = DEFAULT_COMMAND_TIMEOUT;
    }

    /**
     * Execute the command asynchronously.
     * Please notice that the commands will only executed one after another.
     * The command will wait until the su process is free.
     * @param callback The callback instance
     */
    public void executeAsync(SuperUserCommandCallback callback) {
        mCallback = callback;

        // Thread is running
        if (mThread != null) return;

        // Create a new thread
        mThread = new SuperUserCommandThread();

        // Starts a thread
        mThread.start();
    }

    /**
     * Execute the command and return whether the command was executed.
     * It will only return false if the app wasn't granted superuser permissions, like {@link #superuserWasSuccessful()}.
     * It will also return true if the command itself returns error outputs. To check this case you should use {@link #commandWasSuccessful()} instead.
     * Please consider to use {@link #executeAsync} instead of this and execute the command asynchronously.
     * @return Gets whether the execution was successful.
     */
    public boolean execute() {
        String tmpLine;
        List<String> tmpList = new ArrayList<>();

        mSuperUserFailed = false;

        // Opps, we don't have superuser permissions
        // Did you run SuperUser.askForPermissions()?
        if (!SuperUser.hasPermissions()) {
            mSuperUserFailed = true;
            return false;
        }

        // Thread safe
        synchronized (SuperUser.getProcess()) {
            try {
                // Gets the streams
                DataOutputStream dataOutputStream = new DataOutputStream(SuperUser.getProcess().getOutputStream());
                BufferedReader bufferedInputReader = new BufferedReader(new InputStreamReader(SuperUser.getProcess().getInputStream()));
                BufferedReader bufferedErrorReader = new BufferedReader(new InputStreamReader(SuperUser.getProcess().getErrorStream()));

                // Sends the command
                for (String command : mCommands) {
                    if (!mHideInput) // Check if we want to hide this
                        Logger.getInstance().logInfo("SuperUser", "< " + command);
                    dataOutputStream.writeBytes(command + "\n");
                }
                dataOutputStream.flush();

                // TODO: This class cannot execute commands without any output (standard and error). These commands will run until the timeout will kill them!

                // Start waiting
                long timeStarted = System.currentTimeMillis();

                // Wait for first data
                while (!bufferedInputReader.ready() && !bufferedErrorReader.ready()) {
                    try {
                        // Waiting
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    long timeNow = System.currentTimeMillis();

                    // TimeOut
                    if (timeNow - timeStarted >= mTimeout) break;
                }

                // We want to read the data as binary
                if (mBinaryStandardOutput) {
                    int len;
                    byte[] buffer = new byte[1024];

                    // Byte buffer
                    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(1024);

                    // Need the direct input stream
                    InputStream inputStream = SuperUser.getProcess().getInputStream();

                    do {
                        while (bufferedInputReader.ready()) {
                            // Read to buffer
                            len = inputStream.read(buffer);

                            // Write to buffer
                            byteArrayBuffer.append(buffer, 0, len);
                        }

                        // Fix: Wait for the buffer and try again
                        try {
                            // Sometimes cat is to slow.
                            // If there is no data anymore we will wait 100ms and check again.
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } while (bufferedInputReader.ready());

                    mOutputStandardBinary = byteArrayBuffer.toByteArray();
                } else {
                    // Reads the standard output as text
                    tmpList.clear();
                    while (bufferedInputReader.ready()) {
                        tmpLine = bufferedInputReader.readLine();

                        // End of data
                        if (tmpLine == null) break;

                        if (!mHideStandardOutput)
                            Logger.getInstance().logInfo("SuperUser", "> " + tmpLine);

                        tmpList.add(tmpLine);
                    }
                    // Convert list to array
                    mOutputStandard = tmpList.toArray(new String[tmpList.size()]);
                }

                // Reads the error output
                tmpList.clear();
                while (bufferedErrorReader.ready()) {
                    tmpLine = bufferedErrorReader.readLine();

                    // End of data
                    if (tmpLine == null) break;

                    if (!mHideErrorOutput)
                        Logger.getInstance().logError("SuperUser", "> " + tmpLine);

                    tmpList.add(tmpLine);
                }
                // Convert list to array
                mOutputError = tmpList.toArray(new String[tmpList.size()]);

                // Done
                return true;
            } catch (IOException e) {
                e.printStackTrace();

                mSuperUserFailed = true;

                // Command failed
                return false;
            }
        }
    }


    /**
     * Thread to executes the command asynchronously
     */
    private class SuperUserCommandThread extends Thread {
        @Override
        public void run() {

            super.run();

            // Executes the command
            execute();

            if (mCallback != null)
                mCallback.onFinished(SuperUserCommand.this);
        }
    }
}




Java Source Code List

de.arcus.framework.ApplicationTest.java
de.arcus.framework.crashhandler.CrashActivity.java
de.arcus.framework.crashhandler.CrashHandler.java
de.arcus.framework.logger.Logger.java
de.arcus.framework.settings.AppSettings.java
de.arcus.framework.superuser.SuperUserCommandCallback.java
de.arcus.framework.superuser.SuperUserCommand.java
de.arcus.framework.superuser.SuperUserTools.java
de.arcus.framework.superuser.SuperUser.java
de.arcus.framework.utils.FileTools.java
de.arcus.framework.utils.MediaScanner.java
de.arcus.playmusicexporter2.ApplicationTest.java
de.arcus.playmusicexporter2.activitys.MusicTrackDetailActivity.java
de.arcus.playmusicexporter2.activitys.MusicTrackListActivity.java
de.arcus.playmusicexporter2.adapter.MusicTrackAdapter.java
de.arcus.playmusicexporter2.adapter.MusicTrackListAdapter.java
de.arcus.playmusicexporter2.fragments.MusicTrackDetailFragment.java
de.arcus.playmusicexporter2.fragments.MusicTrackListFragment.java
de.arcus.playmusicexporter2.fragments.NavigationDrawerFragment.java
de.arcus.playmusicexporter2.utils.ImageViewLoader.java
de.arcus.playmusicexporter2.utils.MusicPathBuilder.java
de.arcus.playmusiclib.AllAccessExporter.java
de.arcus.playmusiclib.ApplicationTest.java
de.arcus.playmusiclib.PlayMusicManager.java
de.arcus.playmusiclib.datasources.AlbumDataSource.java
de.arcus.playmusiclib.datasources.ArtistDataSource.java
de.arcus.playmusiclib.datasources.DataSource.java
de.arcus.playmusiclib.datasources.MusicTrackDataSource.java
de.arcus.playmusiclib.datasources.PlaylistDataSource.java
de.arcus.playmusiclib.enums.ID3v2Version.java
de.arcus.playmusiclib.exceptions.CouldNotOpenDatabaseException.java
de.arcus.playmusiclib.exceptions.NoSuperUserException.java
de.arcus.playmusiclib.exceptions.PlayMusicNotFoundException.java
de.arcus.playmusiclib.items.Album.java
de.arcus.playmusiclib.items.Artist.java
de.arcus.playmusiclib.items.MusicTrackList.java
de.arcus.playmusiclib.items.MusicTrack.java
de.arcus.playmusiclib.items.Playlist.java