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