Move BasicShellCommandHandler to frameworks/lib/modules-utils

BasicShellCommandHandler is used by mainline modules and the
framwork. There is a new repo that was created for putting
this kind of utility class. Move BasicShellCommandHandler for
the incoming ConnectivityService mainline and updating the
related usage.

Bug: 170598012
Test: m ; verify with adb shell cmd
Change-Id: Ida30c877116090616d4bf3f87fdad835446dac84
diff --git a/Android.bp b/Android.bp
index 9b8e018..4f1284d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -626,6 +626,7 @@
         "av-types-aidl-java",
         "mediatranscoding_aidl_interface-java",
         "soundtrigger_middleware-aidl-java",
+        "modules-utils-os",
     ],
 }
 
@@ -1267,7 +1268,6 @@
 filegroup {
     name: "framework-telephony-common-shared-srcs",
     srcs: [
-        "core/java/android/os/BasicShellCommandHandler.java",
         "core/java/android/os/RegistrantList.java",
         "core/java/android/os/Registrant.java",
         "core/java/android/util/IndentingPrintWriter.java",
@@ -1350,7 +1350,6 @@
     name: "framework-wifi-service-shared-srcs",
     srcs: [
         "core/java/android/net/InterfaceConfiguration.java",
-        "core/java/android/os/BasicShellCommandHandler.java",
         "core/java/android/util/BackupUtils.java",
         "core/java/android/util/Rational.java",
         "core/java/com/android/internal/util/FastXmlSerializer.java",
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index 1e72062..cc20213 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -20,10 +20,11 @@
 import android.app.AppGlobals;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.os.BasicShellCommandHandler;
 import android.os.Binder;
 import android.os.UserHandle;
 
+import com.android.modules.utils.BasicShellCommandHandler;
+
 import java.io.PrintWriter;
 
 public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 822b40b..bbdb5e9 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -5575,7 +5575,6 @@
 android.os.BadParcelableException
 android.os.BaseBundle$NoImagePreloadHolder
 android.os.BaseBundle
-android.os.BasicShellCommandHandler
 android.os.BatteryManager
 android.os.BatteryManagerInternal
 android.os.BatteryProperty$1
@@ -11756,6 +11755,7 @@
 com.android.net.module.annotation.VisibleForTesting
 com.android.net.module.annotation.WorkerThread
 com.android.net.module.util.InetAddressUtils
+com.android.modules.utils.BasicShellCommandHandler
 com.android.okhttp.Address
 com.android.okhttp.AndroidShimResponseCache
 com.android.okhttp.Authenticator
diff --git a/core/java/android/os/BasicShellCommandHandler.java b/core/java/android/os/BasicShellCommandHandler.java
deleted file mode 100644
index 366da3d..0000000
--- a/core/java/android/os/BasicShellCommandHandler.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-/**
- * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. This is meant to
- * be copied into mainline modules, so this class must not use any hidden APIs.
- *
- * @hide
- */
-public abstract class BasicShellCommandHandler {
-    static final String TAG = "ShellCommand";
-    static final boolean DEBUG = false;
-
-    private Binder mTarget;
-    private FileDescriptor mIn;
-    private FileDescriptor mOut;
-    private FileDescriptor mErr;
-    private String[] mArgs;
-
-    private String mCmd;
-    private int mArgPos;
-    private String mCurArgData;
-
-    private FileInputStream mFileIn;
-    private FileOutputStream mFileOut;
-    private FileOutputStream mFileErr;
-
-    private PrintWriter mOutPrintWriter;
-    private PrintWriter mErrPrintWriter;
-    private InputStream mInputStream;
-
-    public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, int firstArgPos) {
-        mTarget = target;
-        mIn = in;
-        mOut = out;
-        mErr = err;
-        mArgs = args;
-        mCmd = null;
-        mArgPos = firstArgPos;
-        mCurArgData = null;
-        mFileIn = null;
-        mFileOut = null;
-        mFileErr = null;
-        mOutPrintWriter = null;
-        mErrPrintWriter = null;
-        mInputStream = null;
-    }
-
-    public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args) {
-        String cmd;
-        int start;
-        if (args != null && args.length > 0) {
-            cmd = args[0];
-            start = 1;
-        } else {
-            cmd = null;
-            start = 0;
-        }
-        init(target, in, out, err, args, start);
-        mCmd = cmd;
-
-        if (DEBUG) {
-            RuntimeException here = new RuntimeException("here");
-            here.fillInStackTrace();
-            Log.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
-            Log.d(TAG, "Calling uid=" + Binder.getCallingUid()
-                    + " pid=" + Binder.getCallingPid());
-        }
-        int res = -1;
-        try {
-            res = onCommand(mCmd);
-            if (DEBUG) Log.d(TAG, "Executed command " + mCmd + " on " + mTarget);
-        } catch (Throwable e) {
-            // Unlike usual calls, in this case if an exception gets thrown
-            // back to us we want to print it back in to the dump data, since
-            // that is where the caller expects all interesting information to
-            // go.
-            PrintWriter eout = getErrPrintWriter();
-            eout.println();
-            eout.println("Exception occurred while executing '" + mCmd + "':");
-            e.printStackTrace(eout);
-        } finally {
-            if (DEBUG) Log.d(TAG, "Flushing output streams on " + mTarget);
-            if (mOutPrintWriter != null) {
-                mOutPrintWriter.flush();
-            }
-            if (mErrPrintWriter != null) {
-                mErrPrintWriter.flush();
-            }
-            if (DEBUG) Log.d(TAG, "Sending command result on " + mTarget);
-        }
-        if (DEBUG) Log.d(TAG, "Finished command " + mCmd + " on " + mTarget);
-        return res;
-    }
-
-    /**
-     * Return the raw FileDescriptor for the output stream.
-     */
-    public FileDescriptor getOutFileDescriptor() {
-        return mOut;
-    }
-
-    /**
-     * Return direct raw access (not buffered) to the command's output data stream.
-     */
-    public OutputStream getRawOutputStream() {
-        if (mFileOut == null) {
-            mFileOut = new FileOutputStream(mOut);
-        }
-        return mFileOut;
-    }
-
-    /**
-     * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
-     */
-    public PrintWriter getOutPrintWriter() {
-        if (mOutPrintWriter == null) {
-            mOutPrintWriter = new PrintWriter(getRawOutputStream());
-        }
-        return mOutPrintWriter;
-    }
-
-    /**
-     * Return the raw FileDescriptor for the error stream.
-     */
-    public FileDescriptor getErrFileDescriptor() {
-        return mErr;
-    }
-
-    /**
-     * Return direct raw access (not buffered) to the command's error output data stream.
-     */
-    public OutputStream getRawErrorStream() {
-        if (mFileErr == null) {
-            mFileErr = new FileOutputStream(mErr);
-        }
-        return mFileErr;
-    }
-
-    /**
-     * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
-     */
-    public PrintWriter getErrPrintWriter() {
-        if (mErr == null) {
-            return getOutPrintWriter();
-        }
-        if (mErrPrintWriter == null) {
-            mErrPrintWriter = new PrintWriter(getRawErrorStream());
-        }
-        return mErrPrintWriter;
-    }
-
-    /**
-     * Return the raw FileDescriptor for the input stream.
-     */
-    public FileDescriptor getInFileDescriptor() {
-        return mIn;
-    }
-
-    /**
-     * Return direct raw access (not buffered) to the command's input data stream.
-     */
-    public InputStream getRawInputStream() {
-        if (mFileIn == null) {
-            mFileIn = new FileInputStream(mIn);
-        }
-        return mFileIn;
-    }
-
-    /**
-     * Return buffered access to the command's {@link #getRawInputStream()}.
-     */
-    public InputStream getBufferedInputStream() {
-        if (mInputStream == null) {
-            mInputStream = new BufferedInputStream(getRawInputStream());
-        }
-        return mInputStream;
-    }
-
-    /**
-     * Return the next option on the command line -- that is an argument that
-     * starts with '-'.  If the next argument is not an option, null is returned.
-     */
-    public String getNextOption() {
-        if (mCurArgData != null) {
-            String prev = mArgs[mArgPos - 1];
-            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
-        }
-        if (mArgPos >= mArgs.length) {
-            return null;
-        }
-        String arg = mArgs[mArgPos];
-        if (!arg.startsWith("-")) {
-            return null;
-        }
-        mArgPos++;
-        if (arg.equals("--")) {
-            return null;
-        }
-        if (arg.length() > 1 && arg.charAt(1) != '-') {
-            if (arg.length() > 2) {
-                mCurArgData = arg.substring(2);
-                return arg.substring(0, 2);
-            } else {
-                mCurArgData = null;
-                return arg;
-            }
-        }
-        mCurArgData = null;
-        return arg;
-    }
-
-    /**
-     * Return the next argument on the command line, whatever it is; if there are
-     * no arguments left, return null.
-     */
-    public String getNextArg() {
-        if (mCurArgData != null) {
-            String arg = mCurArgData;
-            mCurArgData = null;
-            return arg;
-        } else if (mArgPos < mArgs.length) {
-            return mArgs[mArgPos++];
-        } else {
-            return null;
-        }
-    }
-
-    public String peekNextArg() {
-        if (mCurArgData != null) {
-            return mCurArgData;
-        } else if (mArgPos < mArgs.length) {
-            return mArgs[mArgPos];
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * @return all the remaining arguments in the command without moving the current position.
-     */
-    public String[] peekRemainingArgs() {
-        int remaining = getRemainingArgsCount();
-        String[] args = new String[remaining];
-        for (int pos = mArgPos; pos < mArgs.length; pos++) {
-            args[pos - mArgPos] = mArgs[pos];
-        }
-        return args;
-    }
-
-    /**
-     * Returns number of arguments that haven't been processed yet.
-     */
-    public int getRemainingArgsCount() {
-        if (mArgPos >= mArgs.length) {
-            return 0;
-        }
-        return mArgs.length - mArgPos;
-    }
-
-    /**
-     * Return the next argument on the command line, whatever it is; if there are
-     * no arguments left, throws an IllegalArgumentException to report this to the user.
-     */
-    public String getNextArgRequired() {
-        String arg = getNextArg();
-        if (arg == null) {
-            String prev = mArgs[mArgPos - 1];
-            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
-        }
-        return arg;
-    }
-
-    public int handleDefaultCommands(String cmd) {
-        if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
-            onHelp();
-        } else {
-            getOutPrintWriter().println("Unknown command: " + cmd);
-        }
-        return -1;
-    }
-
-    public Binder getTarget() {
-        return mTarget;
-    }
-
-    public String[] getAllArgs() {
-        return mArgs;
-    }
-
-    /**
-     * Implement parsing and execution of a command.  If it isn't a command you understand,
-     * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
-     * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
-     * to process additional command line arguments.  Command output can be written to
-     * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
-     *
-     * <p class="caution">Note that no permission checking has been done before entering this
-     * function, so you need to be sure to do your own security verification for any commands you
-     * are executing.  The easiest way to do this is to have the ShellCommand contain
-     * only a reference to your service's aidl interface, and do all of your command
-     * implementations on top of that -- that way you can rely entirely on your executing security
-     * code behind that interface.</p>
-     *
-     * @param cmd The first command line argument representing the name of the command to execute.
-     * @return Return the command result; generally 0 or positive indicates success and
-     * negative values indicate error.
-     */
-    public abstract int onCommand(String cmd);
-
-    /**
-     * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
-     */
-    public abstract void onHelp();
-}
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 3358ce1..a2173a6 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -19,15 +19,9 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Slog;
 
-import com.android.internal.util.FastPrintWriter;
+import com.android.modules.utils.BasicShellCommandHandler;
 
-import java.io.BufferedInputStream;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
 
 /**
  * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}.
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index c110b26..c85b5d7 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -18,9 +18,10 @@
 package com.android.internal.os;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.os.BasicShellCommandHandler;
 import android.os.Build;
 
+import com.android.modules.utils.BasicShellCommandHandler;
+
 import java.io.PrintStream;
 
 public abstract class BaseCommand {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d586f00..1eba37d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -137,7 +137,6 @@
 import android.net.shared.PrivateDnsConfig;
 import android.net.util.MultinetworkPolicyTracker;
 import android.net.util.NetdService;
-import android.os.BasicShellCommandHandler;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -190,6 +189,7 @@
 import com.android.internal.util.LocationPermissionChecker;
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.XmlUtils;
+import com.android.modules.utils.BasicShellCommandHandler;
 import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
 import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
 import com.android.server.am.BatteryStatsService;
diff --git a/services/core/java/com/android/server/adb/AdbShellCommand.java b/services/core/java/com/android/server/adb/AdbShellCommand.java
index 7691852..d7e95df 100644
--- a/services/core/java/com/android/server/adb/AdbShellCommand.java
+++ b/services/core/java/com/android/server/adb/AdbShellCommand.java
@@ -16,7 +16,7 @@
 
 package com.android.server.adb;
 
-import android.os.BasicShellCommandHandler;
+import com.android.modules.utils.BasicShellCommandHandler;
 
 import java.io.PrintWriter;
 import java.util.Objects;
diff --git a/services/core/java/com/android/server/location/LocationShellCommand.java b/services/core/java/com/android/server/location/LocationShellCommand.java
index 8c1afab0..7d3ccbf 100644
--- a/services/core/java/com/android/server/location/LocationShellCommand.java
+++ b/services/core/java/com/android/server/location/LocationShellCommand.java
@@ -16,9 +16,10 @@
 
 package com.android.server.location;
 
-import android.os.BasicShellCommandHandler;
 import android.os.UserHandle;
 
+import com.android.modules.utils.BasicShellCommandHandler;
+
 import java.io.PrintWriter;
 import java.util.Objects;
 
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index d235c80..dc96df6 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -89,8 +89,6 @@
 rule android.util.LocalLog* com.android.wifi.x.@0
 rule android.util.Rational* com.android.wifi.x.@0
 
-rule android.os.BasicShellCommandHandler* com.android.wifi.x.@0
-
 # Use our statically linked bouncy castle library
 rule org.bouncycastle.** com.android.wifi.x.@0
 # Use our statically linked protobuf library