1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.util.Slog; 21 22 import com.android.modules.utils.BasicShellCommandHandler; 23 24 import java.io.FileDescriptor; 25 26 /** 27 * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. 28 * @hide 29 */ 30 public abstract class ShellCommand extends BasicShellCommandHandler { 31 private ShellCallback mShellCallback; 32 private ResultReceiver mResultReceiver; 33 exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)34 public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err, 35 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 36 mShellCallback = callback; 37 mResultReceiver = resultReceiver; 38 final int result = super.exec(target, in, out, err, args); 39 40 if (mResultReceiver != null) { 41 mResultReceiver.send(result, null); 42 } 43 44 return result; 45 } 46 47 /** 48 * Adopt the ResultReceiver that was given to this shell command from it, taking 49 * it over. Primarily used to dispatch to another shell command. Once called, 50 * this shell command will no longer return its own result when done. 51 */ adoptResultReceiver()52 public ResultReceiver adoptResultReceiver() { 53 ResultReceiver rr = mResultReceiver; 54 mResultReceiver = null; 55 return rr; 56 } 57 58 /** 59 * Helper for just system services to ask the shell to open an output file. 60 * @hide 61 */ openFileForSystem(String path, String mode)62 public ParcelFileDescriptor openFileForSystem(String path, String mode) { 63 if (DEBUG) Slog.d(TAG, "openFileForSystem: " + path + " mode=" + mode); 64 try { 65 ParcelFileDescriptor pfd = getShellCallback().openFile(path, 66 "u:r:system_server:s0", mode); 67 if (pfd != null) { 68 if (DEBUG) Slog.d(TAG, "Got file: " + pfd); 69 return pfd; 70 } 71 } catch (RuntimeException e) { 72 if (DEBUG) Slog.d(TAG, "Failure opening file: " + e.getMessage()); 73 getErrPrintWriter().println("Failure opening file: " + e.getMessage()); 74 } 75 if (DEBUG) Slog.d(TAG, "Error: Unable to open file: " + path); 76 getErrPrintWriter().println("Error: Unable to open file: " + path); 77 78 String suggestedPath = "/data/local/tmp/"; 79 if (path == null || !path.startsWith(suggestedPath)) { 80 getErrPrintWriter().println("Consider using a file under " + suggestedPath); 81 } 82 return null; 83 } 84 handleDefaultCommands(String cmd)85 public int handleDefaultCommands(String cmd) { 86 if ("dump".equals(cmd)) { 87 String[] newArgs = new String[getAllArgs().length-1]; 88 System.arraycopy(getAllArgs(), 1, newArgs, 0, getAllArgs().length-1); 89 getTarget().doDump(getOutFileDescriptor(), getOutPrintWriter(), newArgs); 90 return 0; 91 } 92 return super.handleDefaultCommands(cmd); 93 } 94 95 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) peekNextArg()96 public String peekNextArg() { 97 return super.peekNextArg(); 98 } 99 100 /** 101 * Return the {@link ShellCallback} for communicating back with the calling shell. 102 */ getShellCallback()103 public ShellCallback getShellCallback() { 104 return mShellCallback; 105 } 106 } 107