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; 209461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport com.android.internal.util.FastPrintWriter; 219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2272cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedyimport java.io.BufferedInputStream; 239461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport java.io.FileDescriptor; 2472cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedyimport java.io.FileInputStream; 259461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport java.io.FileOutputStream; 2672cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedyimport java.io.InputStream; 272e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackbornimport java.io.OutputStream; 289461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornimport java.io.PrintWriter; 299461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 309461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn/** 312e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. 329461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * @hide 339461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */ 349461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackbornpublic abstract class ShellCommand { 359461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn static final String TAG = "ShellCommand"; 369461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn static final boolean DEBUG = false; 379461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 389461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private Binder mTarget; 399461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private FileDescriptor mIn; 409461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private FileDescriptor mOut; 419461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private FileDescriptor mErr; 429461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private String[] mArgs; 439461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private ResultReceiver mResultReceiver; 449461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 459461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private String mCmd; 469461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private int mArgPos; 479461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private String mCurArgData; 489461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 492e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn private FileInputStream mFileIn; 502e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn private FileOutputStream mFileOut; 512e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn private FileOutputStream mFileErr; 522e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn 539461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private FastPrintWriter mOutPrintWriter; 549461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn private FastPrintWriter mErrPrintWriter; 5572cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy private InputStream mInputStream; 569461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 573cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err, 583cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn String[] args, int firstArgPos) { 599461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mTarget = target; 609461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mIn = in; 619461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mOut = out; 629461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mErr = err; 639461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mArgs = args; 643cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn mResultReceiver = null; 653cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn mCmd = null; 663cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn mArgPos = firstArgPos; 679461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mCurArgData = null; 682e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mFileIn = null; 692e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mFileOut = null; 702e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mFileErr = null; 719461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mOutPrintWriter = null; 729461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mErrPrintWriter = null; 732e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mInputStream = null; 743cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn } 753cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn 763cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err, 773cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn String[] args, ResultReceiver resultReceiver) { 783cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn String cmd; 793cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn int start; 803cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn if (args != null && args.length > 0) { 813cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn cmd = args[0]; 823cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn start = 1; 833cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn } else { 843cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn cmd = null; 853cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn start = 0; 863cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn } 873cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn init(target, in, out, err, args, start); 883cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn mCmd = cmd; 893cdb56efea044112bfe1b97b3ed78ee05e0dba46Dianne Hackborn mResultReceiver = resultReceiver; 909461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 919461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (DEBUG) Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget); 929461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn int res = -1; 939461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn try { 949461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn res = onCommand(mCmd); 959461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget); 969461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } catch (SecurityException e) { 979461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn PrintWriter eout = getErrPrintWriter(); 989461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn eout.println("Security exception: " + e.getMessage()); 999461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn eout.println(); 1009461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn e.printStackTrace(eout); 1019461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } catch (Throwable e) { 1029461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn // Unlike usual calls, in this case if an exception gets thrown 1039461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn // back to us we want to print it back in to the dump data, since 1049461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn // that is where the caller expects all interesting information to 1059461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn // go. 1069461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn PrintWriter eout = getErrPrintWriter(); 1079461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn eout.println(); 1089461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn eout.println("Exception occurred while dumping:"); 1099461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn e.printStackTrace(eout); 1109461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } finally { 1119461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget); 1129461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mOutPrintWriter != null) { 1139461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mOutPrintWriter.flush(); 1149461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1159461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mErrPrintWriter != null) { 1169461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mErrPrintWriter.flush(); 1179461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1189461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget); 1199461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mResultReceiver.send(res, null); 1209461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget); 1222e44107bf7d9ad97833933422ccd241bf53ff50cDianne Hackborn return res; 1239461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1249461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 1252e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 1262e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Return direct raw access (not buffered) to the command's output data stream. 1272e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 1282e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn public OutputStream getRawOutputStream() { 1292e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn if (mFileOut == null) { 1302e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mFileOut = new FileOutputStream(mOut); 1312e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn } 1322e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn return mFileOut; 1332e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn } 1342e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn 1352e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 1362e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}. 1372e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 1389461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public PrintWriter getOutPrintWriter() { 1399461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mOutPrintWriter == null) { 1402e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mOutPrintWriter = new FastPrintWriter(getRawOutputStream()); 1419461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1429461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return mOutPrintWriter; 1439461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1449461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 1452e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 1462e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Return direct raw access (not buffered) to the command's error output data stream. 1472e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 1482e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn public OutputStream getRawErrorStream() { 1492e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn if (mFileErr == null) { 1502e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mFileErr = new FileOutputStream(mErr); 1512e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn } 1522e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn return mFileErr; 1532e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn } 1542e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn 1552e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 1562e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}. 1572e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 1589461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public PrintWriter getErrPrintWriter() { 1599461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mErr == null) { 1609461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return getOutPrintWriter(); 1619461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1629461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mErrPrintWriter == null) { 1632e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mErrPrintWriter = new FastPrintWriter(getRawErrorStream()); 1649461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1659461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return mErrPrintWriter; 1669461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1679461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 1682e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 1692e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Return direct raw access (not buffered) to the command's input data stream. 1702e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 1712e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn public InputStream getRawInputStream() { 1722e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn if (mFileIn == null) { 1732e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mFileIn = new FileInputStream(mIn); 1742e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn } 1752e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn return mFileIn; 1762e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn } 1772e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn 1782e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 1792e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Return buffered access to the command's {@link #getRawInputStream()}. 1802e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 1812e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn public InputStream getBufferedInputStream() { 18272cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy if (mInputStream == null) { 1832e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn mInputStream = new BufferedInputStream(getRawInputStream()); 18472cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy } 18572cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy return mInputStream; 18672cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy } 18772cfcd02b89838264b018e9b9417d2829c87b7e2Todd Kennedy 1889461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn /** 1899461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * Return the next option on the command line -- that is an argument that 1909461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * starts with '-'. If the next argument is not an option, null is returned. 1919461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */ 1929461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public String getNextOption() { 1939461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mCurArgData != null) { 1949461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn String prev = mArgs[mArgPos - 1]; 1959461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn throw new IllegalArgumentException("No argument expected after \"" + prev + "\""); 1969461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1979461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mArgPos >= mArgs.length) { 1989461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return null; 1999461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2009461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn String arg = mArgs[mArgPos]; 2019461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (!arg.startsWith("-")) { 2029461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return null; 2039461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2049461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mArgPos++; 2059461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (arg.equals("--")) { 2069461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return null; 2079461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2089461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (arg.length() > 1 && arg.charAt(1) != '-') { 2099461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (arg.length() > 2) { 2109461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mCurArgData = arg.substring(2); 2119461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return arg.substring(0, 2); 2129461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } else { 2139461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mCurArgData = null; 2149461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return arg; 2159461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2169461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2179461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mCurArgData = null; 2189461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return arg; 2199461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2209461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn /** 2229461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * Return the next argument on the command line, whatever it is; if there are 2239461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * no arguments left, return null. 2249461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */ 2259461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public String getNextArg() { 2269461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mCurArgData != null) { 2279461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn String arg = mCurArgData; 2289461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mCurArgData = null; 2299461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return arg; 2309461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } else if (mArgPos < mArgs.length) { 2319461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return mArgs[mArgPos++]; 2329461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } else { 2339461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return null; 2349461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2359461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2369461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 237c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski public String peekNextArg() { 238c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski if (mCurArgData != null) { 239c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski return mCurArgData; 240c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski } else if (mArgPos < mArgs.length) { 241c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski return mArgs[mArgPos]; 242c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski } else { 243c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski return null; 244c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski } 245c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski } 246c17d8b79afd02133b021d89b536c812578308329Filip Gruszczynski 2479461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn /** 2489461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * Return the next argument on the command line, whatever it is; if there are 2499461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * no arguments left, throws an IllegalArgumentException to report this to the user. 2509461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */ 2519461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public String getNextArgRequired() { 2529461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn String arg = getNextArg(); 2539461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (arg == null) { 2549461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn String prev = mArgs[mArgPos - 1]; 2559461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn throw new IllegalArgumentException("Argument expected after \"" + prev + "\""); 2569461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2579461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return arg; 2589461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2599461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2609461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public int handleDefaultCommands(String cmd) { 2619461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if ("dump".equals(cmd)) { 2629461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn String[] newArgs = new String[mArgs.length-1]; 2639461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn System.arraycopy(mArgs, 1, newArgs, 0, mArgs.length-1); 2649461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mTarget.doDump(mOut, getOutPrintWriter(), newArgs); 2659461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return 0; 2669461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } else if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) { 2679461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn onHelp(); 2689461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } else { 2699461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn getOutPrintWriter().println("Unknown command: " + cmd); 2709461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2719461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return -1; 2729461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2739461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2742e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 2752e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Implement parsing and execution of a command. If it isn't a command you understand, 2762e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * call {@link #handleDefaultCommands(String)} and return its result as a last resort. 2772e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * User {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()} 2782e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * to process additional command line arguments. Command output can be written to 2792e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}. 2802e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * 2812e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * <p class="caution">Note that no permission checking has been done before entering this function, 2822e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * so you need to be sure to do your own security verification for any commands you 2832e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * are executing. The easiest way to do this is to have the ShellCommand contain 2842e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * only a reference to your service's aidl interface, and do all of your command 2852e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * implementations on top of that -- that way you can rely entirely on your executing security 2862e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * code behind that interface.</p> 2872e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * 2882e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * @param cmd The first command line argument representing the name of the command to execute. 2892e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * @return Return the command result; generally 0 or positive indicates success and 2902e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * negative values indicate error. 2912e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 2929461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public abstract int onCommand(String cmd); 2939461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2942e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn /** 2952e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn * Implement this to print help text about your command to {@link #getOutPrintWriter()}. 2962e931f56c77cf53df9daf99d5afdd7bc4c109a54Dianne Hackborn */ 2979461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public abstract void onHelp(); 2989461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn} 299