19461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn/*
29461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * Copyright (C) 2015 The Android Open Source Project
39461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn *
49461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
59461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * you may not use this file except in compliance with the License.
69461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * You may obtain a copy of the License at
79461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn *
89461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
99461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn *
109461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
119461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
129461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * See the License for the specific language governing permissions and
149461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * limitations under the License.
159461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */
169461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
179461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornpackage android.os;
189461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
199461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport android.util.Slog;
20c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn
219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport com.android.internal.util.FastPrintWriter;
229461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
2372cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedyimport java.io.BufferedInputStream;
249461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport java.io.FileDescriptor;
2572cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedyimport java.io.FileInputStream;
269461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport java.io.FileOutputStream;
2772cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedyimport java.io.InputStream;
282e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackbornimport java.io.OutputStream;
299461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport java.io.PrintWriter;
309461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
319461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn/**
322e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}.
339461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * @hide
349461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */
359461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornpublic abstract class ShellCommand {
369461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    static final String TAG = "ShellCommand";
379461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    static final boolean DEBUG = false;
389461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
399461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private Binder mTarget;
409461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private FileDescriptor mIn;
419461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private FileDescriptor mOut;
429461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private FileDescriptor mErr;
439461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private String[] mArgs;
44354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn    private ShellCallback mShellCallback;
459461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private ResultReceiver mResultReceiver;
469461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
479461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private String mCmd;
489461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private int mArgPos;
499461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private String mCurArgData;
509461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
512e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    private FileInputStream mFileIn;
522e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    private FileOutputStream mFileOut;
532e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    private FileOutputStream mFileErr;
542e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn
559461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private FastPrintWriter mOutPrintWriter;
569461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    private FastPrintWriter mErrPrintWriter;
5772cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy    private InputStream mInputStream;
589461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
593cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn    public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
60354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn            String[] args, ShellCallback callback, int firstArgPos) {
619461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mTarget = target;
629461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mIn = in;
639461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mOut = out;
649461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mErr = err;
659461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mArgs = args;
66354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn        mShellCallback = callback;
673cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        mResultReceiver = null;
683cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        mCmd = null;
693cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        mArgPos = firstArgPos;
709461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mCurArgData = null;
712e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        mFileIn = null;
722e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        mFileOut = null;
732e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        mFileErr = null;
749461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mOutPrintWriter = null;
759461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mErrPrintWriter = null;
762e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        mInputStream = null;
773cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn    }
783cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn
793cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn    public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
80354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
813cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        String cmd;
823cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        int start;
833cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        if (args != null && args.length > 0) {
843cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn            cmd = args[0];
853cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn            start = 1;
863cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        } else {
873cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn            cmd = null;
883cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn            start = 0;
893cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        }
90354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn        init(target, in, out, err, args, callback, start);
913cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        mCmd = cmd;
923cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn        mResultReceiver = resultReceiver;
939461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
941704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn        if (DEBUG) {
951704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            RuntimeException here = new RuntimeException("here");
961704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            here.fillInStackTrace();
971704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
981704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            Slog.d(TAG, "Calling uid=" + Binder.getCallingUid()
991704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn                    + " pid=" + Binder.getCallingPid() + " ShellCallback=" + getShellCallback());
1001704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn        }
1019461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        int res = -1;
1029461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        try {
1039461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            res = onCommand(mCmd);
1049461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
1059461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } catch (SecurityException e) {
1069461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            PrintWriter eout = getErrPrintWriter();
1079461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            eout.println("Security exception: " + e.getMessage());
1089461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            eout.println();
1099461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            e.printStackTrace(eout);
1109461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } catch (Throwable e) {
1119461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            // Unlike usual calls, in this case if an exception gets thrown
1129461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            // back to us we want to print it back in to the dump data, since
1139461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            // that is where the caller expects all interesting information to
1149461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            // go.
1159461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            PrintWriter eout = getErrPrintWriter();
1169461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            eout.println();
117354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn            eout.println("Exception occurred while executing:");
1189461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            e.printStackTrace(eout);
1199461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } finally {
1209461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget);
1219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            if (mOutPrintWriter != null) {
1229461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn                mOutPrintWriter.flush();
1239461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            }
1249461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            if (mErrPrintWriter != null) {
1259461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn                mErrPrintWriter.flush();
1269461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            }
1279461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget);
128c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn            if (mResultReceiver != null) {
129c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn                mResultReceiver.send(res, null);
130c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn            }
1319461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
1329461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
1332e44107bf7d9ad97833933422ccd241bf53ff50cDianne Hackborn        return res;
1349461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
1359461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
1362e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
137c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     * Adopt the ResultReceiver that was given to this shell command from it, taking
138c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     * it over.  Primarily used to dispatch to another shell command.  Once called,
139c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     * this shell command will no longer return its own result when done.
140c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     */
141c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    public ResultReceiver adoptResultReceiver() {
142c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn        ResultReceiver rr = mResultReceiver;
143c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn        mResultReceiver = null;
144c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn        return rr;
145c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    }
146c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn
147c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    /**
148c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     * Return the raw FileDescriptor for the output stream.
149c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     */
150c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    public FileDescriptor getOutFileDescriptor() {
151c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn        return mOut;
152c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    }
153c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn
154c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    /**
1552e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Return direct raw access (not buffered) to the command's output data stream.
1562e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
1572e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    public OutputStream getRawOutputStream() {
1582e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        if (mFileOut == null) {
1592e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn            mFileOut = new FileOutputStream(mOut);
1602e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        }
1612e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        return mFileOut;
1622e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    }
1632e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn
1642e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
1652e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
1662e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
1679461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public PrintWriter getOutPrintWriter() {
1689461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (mOutPrintWriter == null) {
1692e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn            mOutPrintWriter = new FastPrintWriter(getRawOutputStream());
1709461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
1719461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        return mOutPrintWriter;
1729461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
1739461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
1742e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
175c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     * Return the raw FileDescriptor for the error stream.
176c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     */
177c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    public FileDescriptor getErrFileDescriptor() {
178c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn        return mErr;
179c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    }
180c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn
181c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    /**
1822e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Return direct raw access (not buffered) to the command's error output data stream.
1832e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
1842e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    public OutputStream getRawErrorStream() {
1852e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        if (mFileErr == null) {
1862e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn            mFileErr = new FileOutputStream(mErr);
1872e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        }
1882e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        return mFileErr;
1892e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    }
1902e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn
1912e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
1922e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
1932e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
1949461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public PrintWriter getErrPrintWriter() {
1959461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (mErr == null) {
1969461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return getOutPrintWriter();
1979461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
1989461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (mErrPrintWriter == null) {
1992e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn            mErrPrintWriter = new FastPrintWriter(getRawErrorStream());
2009461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
2019461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        return mErrPrintWriter;
2029461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
2039461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
2042e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
205c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     * Return the raw FileDescriptor for the input stream.
206c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn     */
207c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    public FileDescriptor getInFileDescriptor() {
208c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn        return mIn;
209c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    }
210c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn
211c81983a0c3d7bfe8384dbf48909f4bcf300e36d2Dianne Hackborn    /**
2122e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Return direct raw access (not buffered) to the command's input data stream.
2132e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
2142e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    public InputStream getRawInputStream() {
2152e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        if (mFileIn == null) {
2162e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn            mFileIn = new FileInputStream(mIn);
2172e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        }
2182e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn        return mFileIn;
2192e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    }
2202e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn
2212e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
2222e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Return buffered access to the command's {@link #getRawInputStream()}.
2232e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
2242e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    public InputStream getBufferedInputStream() {
22572cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy        if (mInputStream == null) {
2262e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn            mInputStream = new BufferedInputStream(getRawInputStream());
22772cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy        }
22872cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy        return mInputStream;
22972cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy    }
23072cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy
2319461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    /**
232331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn     * Helper for just system services to ask the shell to open an output file.
233331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn     * @hide
234331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn     */
235ca3872ce36c94090ae18519dc7fe0cf39d834c4aDianne Hackborn    public ParcelFileDescriptor openFileForSystem(String path, String mode) {
2361704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn        if (DEBUG) Slog.d(TAG, "openFileForSystem: " + path + " mode=" + mode);
237331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn        try {
238ca3872ce36c94090ae18519dc7fe0cf39d834c4aDianne Hackborn            ParcelFileDescriptor pfd = getShellCallback().openFile(path,
239ca3872ce36c94090ae18519dc7fe0cf39d834c4aDianne Hackborn                    "u:r:system_server:s0", mode);
240331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn            if (pfd != null) {
2411704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn                if (DEBUG) Slog.d(TAG, "Got file: " + pfd);
242331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn                return pfd;
243331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn            }
244331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn        } catch (RuntimeException e) {
2451704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            if (DEBUG) Slog.d(TAG, "Failure opening file: " + e.getMessage());
246331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn            getErrPrintWriter().println("Failure opening file: " + e.getMessage());
247331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn        }
2481704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn        if (DEBUG) Slog.d(TAG, "Error: Unable to open file: " + path);
249331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn        getErrPrintWriter().println("Error: Unable to open file: " + path);
250331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn        getErrPrintWriter().println("Consider using a file under /data/local/tmp/");
251331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn        return null;
252331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn    }
253331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn
254331084dca66ec2dc0b32f689c7a5c5252e0c7d3fDianne Hackborn    /**
2559461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     * Return the next option on the command line -- that is an argument that
2569461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     * starts with '-'.  If the next argument is not an option, null is returned.
2579461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     */
2589461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public String getNextOption() {
2599461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (mCurArgData != null) {
2609461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            String prev = mArgs[mArgPos - 1];
2619461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
2629461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
2639461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (mArgPos >= mArgs.length) {
2649461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return null;
2659461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
2669461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        String arg = mArgs[mArgPos];
2679461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (!arg.startsWith("-")) {
2689461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return null;
2699461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
2709461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mArgPos++;
2719461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (arg.equals("--")) {
2729461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return null;
2739461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
2749461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (arg.length() > 1 && arg.charAt(1) != '-') {
2759461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            if (arg.length() > 2) {
2769461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn                mCurArgData = arg.substring(2);
2779461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn                return arg.substring(0, 2);
2789461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            } else {
2799461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn                mCurArgData = null;
2809461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn                return arg;
2819461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            }
2829461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
2839461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        mCurArgData = null;
2849461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        return arg;
2859461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
2869461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
2879461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    /**
2889461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     * Return the next argument on the command line, whatever it is; if there are
2899461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     * no arguments left, return null.
2909461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     */
2919461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public String getNextArg() {
2929461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (mCurArgData != null) {
2939461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            String arg = mCurArgData;
2949461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            mCurArgData = null;
2959461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return arg;
2969461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } else if (mArgPos < mArgs.length) {
2979461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return mArgs[mArgPos++];
2989461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } else {
2999461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return null;
3009461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
3019461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
3029461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
303c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski    public String peekNextArg() {
304c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski        if (mCurArgData != null) {
305c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski            return mCurArgData;
306c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski        } else if (mArgPos < mArgs.length) {
307c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski            return mArgs[mArgPos];
308c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski        } else {
309c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski            return null;
310c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski        }
311c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski    }
312c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski
3139461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    /**
3149461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     * Return the next argument on the command line, whatever it is; if there are
3159461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     * no arguments left, throws an IllegalArgumentException to report this to the user.
3169461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn     */
3179461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public String getNextArgRequired() {
3189461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        String arg = getNextArg();
3199461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if (arg == null) {
3209461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            String prev = mArgs[mArgPos - 1];
3219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
3229461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
3239461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        return arg;
3249461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
3259461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
326354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn    /**
327354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn     * Return the {@link ShellCallback} for communicating back with the calling shell.
328354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn     */
329354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn    public ShellCallback getShellCallback() {
330354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn        return mShellCallback;
331354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn    }
332354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn
3339461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public int handleDefaultCommands(String cmd) {
3349461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        if ("dump".equals(cmd)) {
3359461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            String[] newArgs = new String[mArgs.length-1];
3369461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            System.arraycopy(mArgs, 1, newArgs, 0, mArgs.length-1);
3379461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            mTarget.doDump(mOut, getOutPrintWriter(), newArgs);
3389461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            return 0;
3399461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } else if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
3409461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            onHelp();
3419461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        } else {
3429461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn            getOutPrintWriter().println("Unknown command: " + cmd);
3439461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        }
3449461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn        return -1;
3459461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    }
3469461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
3472e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
3482e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Implement parsing and execution of a command.  If it isn't a command you understand,
3492e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
350f3409ceee59a006155915010b11af81a822225aaLeonard Mosescu     * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
3512e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * to process additional command line arguments.  Command output can be written to
3522e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
3532e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     *
3542e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * <p class="caution">Note that no permission checking has been done before entering this function,
3552e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * so you need to be sure to do your own security verification for any commands you
3562e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * are executing.  The easiest way to do this is to have the ShellCommand contain
3572e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * only a reference to your service's aidl interface, and do all of your command
3582e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * implementations on top of that -- that way you can rely entirely on your executing security
3592e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * code behind that interface.</p>
3602e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     *
3612e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * @param cmd The first command line argument representing the name of the command to execute.
3622e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * @return Return the command result; generally 0 or positive indicates success and
3632e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * negative values indicate error.
3642e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
3659461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public abstract int onCommand(String cmd);
3669461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn
3672e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn    /**
3682e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
3692e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn     */
3709461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn    public abstract void onHelp();
3719461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn}
372