Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 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 | |
Artur Satayev | afdb23a | 2019-12-10 17:47:53 +0000 | [diff] [blame] | 19 | import android.compat.annotation.UnsupportedAppUsage; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 20 | import android.util.Slog; |
Dianne Hackborn | c81983a | 2017-10-20 16:16:32 -0700 | [diff] [blame] | 21 | |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 22 | import com.android.internal.util.FastPrintWriter; |
| 23 | |
Todd Kennedy | 72cfcd0 | 2015-11-03 17:08:55 -0800 | [diff] [blame] | 24 | import java.io.BufferedInputStream; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 25 | import java.io.FileDescriptor; |
Todd Kennedy | 72cfcd0 | 2015-11-03 17:08:55 -0800 | [diff] [blame] | 26 | import java.io.FileInputStream; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 27 | import java.io.FileOutputStream; |
Todd Kennedy | 72cfcd0 | 2015-11-03 17:08:55 -0800 | [diff] [blame] | 28 | import java.io.InputStream; |
Dianne Hackborn | 2e931f5 | 2016-01-28 12:21:17 -0800 | [diff] [blame] | 29 | import java.io.OutputStream; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 30 | import java.io.PrintWriter; |
| 31 | |
| 32 | /** |
Dianne Hackborn | 2e931f5 | 2016-01-28 12:21:17 -0800 | [diff] [blame] | 33 | * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 34 | * @hide |
| 35 | */ |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 36 | public abstract class ShellCommand extends BasicShellCommandHandler { |
Dianne Hackborn | 354736e | 2016-08-22 17:00:05 -0700 | [diff] [blame] | 37 | private ShellCallback mShellCallback; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 38 | private ResultReceiver mResultReceiver; |
| 39 | |
Dianne Hackborn | 3cdb56e | 2015-11-11 12:45:44 -0800 | [diff] [blame] | 40 | public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err, |
Dianne Hackborn | 354736e | 2016-08-22 17:00:05 -0700 | [diff] [blame] | 41 | String[] args, ShellCallback callback, ResultReceiver resultReceiver) { |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 42 | mShellCallback = callback; |
Dianne Hackborn | 3cdb56e | 2015-11-11 12:45:44 -0800 | [diff] [blame] | 43 | mResultReceiver = resultReceiver; |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 44 | final int result = super.exec(target, in, out, err, args); |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 45 | |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 46 | if (mResultReceiver != null) { |
| 47 | mResultReceiver.send(result, null); |
Dianne Hackborn | 1704e3c | 2017-10-31 19:55:42 +0000 | [diff] [blame] | 48 | } |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 49 | |
| 50 | return result; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 51 | } |
| 52 | |
Dianne Hackborn | 2e931f5 | 2016-01-28 12:21:17 -0800 | [diff] [blame] | 53 | /** |
Dianne Hackborn | c81983a | 2017-10-20 16:16:32 -0700 | [diff] [blame] | 54 | * Adopt the ResultReceiver that was given to this shell command from it, taking |
| 55 | * it over. Primarily used to dispatch to another shell command. Once called, |
| 56 | * this shell command will no longer return its own result when done. |
| 57 | */ |
| 58 | public ResultReceiver adoptResultReceiver() { |
| 59 | ResultReceiver rr = mResultReceiver; |
| 60 | mResultReceiver = null; |
| 61 | return rr; |
| 62 | } |
| 63 | |
| 64 | /** |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 65 | * Helper for just system services to ask the shell to open an output file. |
| 66 | * @hide |
| 67 | */ |
Dianne Hackborn | ca3872c | 2017-10-30 14:19:32 -0700 | [diff] [blame] | 68 | public ParcelFileDescriptor openFileForSystem(String path, String mode) { |
Dianne Hackborn | 1704e3c | 2017-10-31 19:55:42 +0000 | [diff] [blame] | 69 | if (DEBUG) Slog.d(TAG, "openFileForSystem: " + path + " mode=" + mode); |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 70 | try { |
Dianne Hackborn | ca3872c | 2017-10-30 14:19:32 -0700 | [diff] [blame] | 71 | ParcelFileDescriptor pfd = getShellCallback().openFile(path, |
| 72 | "u:r:system_server:s0", mode); |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 73 | if (pfd != null) { |
Dianne Hackborn | 1704e3c | 2017-10-31 19:55:42 +0000 | [diff] [blame] | 74 | if (DEBUG) Slog.d(TAG, "Got file: " + pfd); |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 75 | return pfd; |
| 76 | } |
| 77 | } catch (RuntimeException e) { |
Dianne Hackborn | 1704e3c | 2017-10-31 19:55:42 +0000 | [diff] [blame] | 78 | if (DEBUG) Slog.d(TAG, "Failure opening file: " + e.getMessage()); |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 79 | getErrPrintWriter().println("Failure opening file: " + e.getMessage()); |
| 80 | } |
Dianne Hackborn | 1704e3c | 2017-10-31 19:55:42 +0000 | [diff] [blame] | 81 | if (DEBUG) Slog.d(TAG, "Error: Unable to open file: " + path); |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 82 | getErrPrintWriter().println("Error: Unable to open file: " + path); |
Robin Lee | 56be27c | 2017-09-14 14:28:26 +0200 | [diff] [blame] | 83 | |
| 84 | String suggestedPath = "/data/local/tmp/"; |
| 85 | if (path == null || !path.startsWith(suggestedPath)) { |
| 86 | getErrPrintWriter().println("Consider using a file under " + suggestedPath); |
| 87 | } |
Dianne Hackborn | 331084d | 2016-10-07 17:57:00 -0700 | [diff] [blame] | 88 | return null; |
| 89 | } |
| 90 | |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 91 | public int handleDefaultCommands(String cmd) { |
| 92 | if ("dump".equals(cmd)) { |
| 93 | String[] newArgs = new String[getAllArgs().length-1]; |
| 94 | System.arraycopy(getAllArgs(), 1, newArgs, 0, getAllArgs().length-1); |
| 95 | getTarget().doDump(getOutFileDescriptor(), getOutPrintWriter(), newArgs); |
| 96 | return 0; |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 97 | } |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 98 | return super.handleDefaultCommands(cmd); |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 99 | } |
| 100 | |
Andrei Onea | 24ec321 | 2019-03-15 17:35:05 +0000 | [diff] [blame] | 101 | @UnsupportedAppUsage |
Filip Gruszczynski | c17d8b7 | 2016-02-03 16:52:59 -0800 | [diff] [blame] | 102 | public String peekNextArg() { |
Makoto Onuki | 4c7073b | 2019-11-04 10:37:15 -0800 | [diff] [blame] | 103 | return super.peekNextArg(); |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 104 | } |
| 105 | |
Dianne Hackborn | 354736e | 2016-08-22 17:00:05 -0700 | [diff] [blame] | 106 | /** |
| 107 | * Return the {@link ShellCallback} for communicating back with the calling shell. |
| 108 | */ |
| 109 | public ShellCallback getShellCallback() { |
| 110 | return mShellCallback; |
| 111 | } |
Dianne Hackborn | 9461b6f | 2015-10-07 17:33:16 -0700 | [diff] [blame] | 112 | } |