Android你不知道的svc命令----解析adb shell svc源码

56 篇文章 0 订阅
8 篇文章 0 订阅

首先执行 adb shell svc bluetooth help看一下

~/debuglogger/mobilelog/APLog_2021_1118_173806__1$ adb shell svc bluetooth help
Control Bluetooth service

usage: svc bluetooth [enable|disable]
         Turn Bluetooth on or off.

然后根据 Control Bluetooth service 字符串查找相关文件

~/projects/MTK_R_6580_2/alps/frameworks$ grep "Control Bluetooth service" ./ -r
frameworks/base/cmds/svc/src/com/android/commands/svc/BluetoothCommand.java:        return "Control Bluetooth service";

frameworks/base/cmds/svc/src/com/android/commands/svc/BluetoothCommand.java

public class BluetoothCommand extends Svc.Command {

    public BluetoothCommand() {
        super("bluetooth");
    }

    @Override
    public String shortHelp() {
        return "Control Bluetooth service";
    }

    @Override
    public String longHelp() {
        return shortHelp() + "\n"
                + "\n"
                + "usage: svc bluetooth [enable|disable]\n"
                + "         Turn Bluetooth on or off.\n\n";
    }

    @Override
    public void run(String[] args) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

        if (adapter == null) {
            System.err.println("Got a null BluetoothAdapter, is the system running?");
            return;
        }

        if (args.length == 2 && "enable".equals(args[1])) {
            adapter.enable();
        } else if (args.length == 2 && "disable".equals(args[1])) {
            adapter.disable();
        } else {
            System.err.println(longHelp());
        }
    }
}

从上面的代码中看到run()会根据传入的参数执行不同的操作,传入 enable 会执行 adapter.enable(); 方法打开蓝牙,传入 disable 会执行 adapter.disable(); 方法关闭蓝牙。

再看看其他的方法,找找有用的信息

public BluetoothCommand() {
    super("bluetooth");		// 这个应该就是 adb shell svc bluetooth 中的 bluetooth
}

shortHelp() 和 longHelp() 应该就是命令的帮助信息模板方法

@Override
public String shortHelp() {
    return "Control Bluetooth service";
}

@Override
public String longHelp() {
    return shortHelp() + "\n"
            + "\n"
            + "usage: svc bluetooth [enable|disable]\n"
            + "         Turn Bluetooth on or off.\n\n";
}

这个类相当简单,是否只要继承Command.Svc 这个类就可以实现类似的功能?再找找系统中是否还有其他继承 Command.Svc 类的子类。搜索结果如下:

~/projects/MTK_R_6580_2/alps/frameworks$ grep "Svc.Command" ./ -r
frameworks/base/cmds/svc/src/com/android/commands/svc/PowerCommand.java:public class PowerCommand extends Svc.Command {
frameworks/base/cmds/svc/src/com/android/commands/svc/NfcCommand.java:public class NfcCommand extends Svc.Command {
frameworks/base/cmds/svc/src/com/android/commands/svc/BluetoothCommand.java:public class BluetoothCommand extends Svc.Command {
frameworks/base/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java:public class SystemServerCommand extends Svc.Command {
frameworks/base/cmds/svc/src/com/android/commands/svc/UsbCommand.java:public class UsbCommand extends Svc.Command {

果然找到一堆支持svc的命令,分析一波,用法如下:

NFC

public String longHelp() {
    return shortHelp() + "\n"
            + "\n"
            + "usage: svc nfc [enable|disable]\n"
            + "         Turn NFC on or off.\n\n";
}

Bluetooth

public String longHelp() {
    return shortHelp() + "\n"
            + "\n"
            + "usage: svc bluetooth [enable|disable]\n"
            + "         Turn Bluetooth on or off.\n\n";
}

USB

public String longHelp() {
    return shortHelp() + "\n"
            + "\n"
            + "usage: svc usb setFunctions [function]\n"
            + "         Set the current usb function. If function is blank, sets to charging.\n"
            + "       svc usb setScreenUnlockedFunctions [function]\n"
            + "         Sets the functions which, if the device was charging, become current on"
                + "screen unlock. If function is blank, turn off this feature.\n"
            + "       svc usb getFunctions\n"
            + "          Gets the list of currently enabled functions\n"
            + "       svc usb resetUsbGadget\n"
            + "          Reset usb gadget\n\n"
            + "possible values of [function] are any of 'mtp', 'ptp', 'rndis', 'midi'\n";
}

system-server

public String longHelp() {
    return shortHelp() + "\n"
            + "\n"
            + "usage: system-server wait-for-crash\n"
            + "         Wait until the system server process crashes.\n\n";
}

power

public String longHelp() {
    return shortHelp() + "\n"
            + "\n"
            + "usage: svc power stayon [true|false|usb|ac|wireless]\n"
            + "         Set the 'keep awake while plugged in' setting.\n"
            + "       svc power reboot [reason]\n"
            + "         Perform a runtime shutdown and reboot device with specified reason.\n"
            + "       svc power shutdown\n"
            + "         Perform a runtime shutdown and power off the device.\n"
            + "       svc power forcesuspend [t]\n"
            + "         Force the system into suspend, ignoring all wakelocks.\n"
            + "         t - Number of milliseconds to wait before issuing force-suspend.\n"
            + "             Helps with devices that can't suspend while plugged in.\n"
            + "             Defaults to " + FORCE_SUSPEND_DELAY_DEFAULT_MILLIS + ".\n"
            + "             When using a delay, you must use the nohup shell modifier:\n"
            + "             'adb shell nohup svc power forcesuspend [time]'\n"
            + "         Use caution; this is dangerous. It puts the device to sleep\n"
            + "         immediately without giving apps or the system an opportunity to\n"
            + "         save their state.\n";
}

再解析一波大佬frameworks/base/cmds/svc/src/com/android/commands/svc/Svc.java

public class Svc {

    public static abstract class Command {
        private String mName;

        public Command(String name) {
            mName = name;
        }

        public String name() {
            return mName;
        }

        public abstract String shortHelp();         // should fit on one short line
        public abstract String longHelp();          // take as much space as you need, 75 col max
        public abstract void run(String[] args);    // run the command
    }

    public static void main(String[] args) {
        if (args.length >= 1) {
            Command c = lookupCommand(args[0]);
            if (c != null) {
                c.run(args);
                return;
            }
        }
        COMMAND_HELP.run(args);
    }

    private static Command lookupCommand(String name) {
        final int N = COMMANDS.length;
        for (int i=0; i<N; i++) {
            Command c = COMMANDS[i];
            if (c.name().equals(name)) {
                return c;
            }
        }
        return null;
    }

    public static final Command COMMAND_HELP = new Command("help") {
        public String shortHelp() {
            return "Show information about the subcommands";
        }
        public String longHelp() {
            return shortHelp();
        }
        public void run(String[] args) {
            if (args.length == 2) {
                Command c = lookupCommand(args[1]);
                if (c != null) {
                    System.err.println(c.longHelp());
                    return;
                }
            }

            System.err.println("Available commands:");
            final int N = COMMANDS.length;
            int maxlen = 0;
            for (int i=0; i<N; i++) {
                Command c = COMMANDS[i];
                int len = c.name().length();
                if (maxlen < len) {
                    maxlen = len;
                }
            }
            String format = "    %-" + maxlen + "s    %s";
            for (int i=0; i<N; i++) {
                Command c = COMMANDS[i];
                System.err.println(String.format(format, c.name(), c.shortHelp()));	//help命令就是把COMMANDS中的所有命令遍历一遍,并且打印 shortHelp() 方法中的信息
            }
        }
    };

    public static final Command[] COMMANDS = new Command[] {
            COMMAND_HELP,
            new PowerCommand(),
            // `svc wifi` has been migrated to WifiShellCommand
            new UsbCommand(),
            new NfcCommand(),
            new BluetoothCommand(),
            new SystemServerCommand(),
    };
}

这个就是一个典型的Java程序,从main()方法开始执行,如果svc后面的参数不为空就执行

public static void main(String[] args) {
    if (args.length >= 1) {
        Command c = lookupCommand(args[0]);		//如果svc后面有参数,就从COMMANDS数组中看是否支持这个参数
        if (c != null) {
            c.run(args);	//如果支持就执行
            return;
        }
    }
    COMMAND_HELP.run(args);//如果svc后面的参数为空,或者COMMANDS中没有这个参数就执行help命令
}

adb shell svc结果显示如下

Available commands:
    help             Show information about the subcommands
    power            Control the power manager
    usb              Control Usb state
    nfc              Control NFC functions
    bluetooth        Control Bluetooth service
    system-server    System server process related command

adb shell which svc

adb shell which svc
/system/bin/svc

adb shell ls /system/bin/svc -al
-rwxr-xr-x 1 root shell 1068 2021-11-19 11:42 /system/bin/svc

adb shell cat /system/bin/svc
#!/system/bin/sh

# `svc wifi` has been migrated to WifiShellCommand,
# simply perform translation to `cmd wifi set-wifi-enabled` here.
if [ "x$1" == "xwifi" ]; then
    # `cmd wifi` by convention uses enabled/disabled
    # instead of enable/disable
    if [ "x$2" == "xenable" ]; then
        exec cmd wifi set-wifi-enabled enabled
    elif [ "x$2" == "xdisable" ]; then
        exec cmd wifi set-wifi-enabled disabled
    else
        echo "Control the Wi-Fi manager"
        echo ""
        echo "usage: svc wifi [enable|disable]"
        echo "         Turn Wi-Fi on or off."
        echo ""
    fi
    exit 1
fi

if [ "x$1" == "xdata" ]; then
    if [ "x$2" == "xenable" ]; then
        exec cmd phone data enable
    elif [ "x$2" == "xdisable" ]; then
        exec cmd phone data disable
    else
        echo "Enable/Disable Mobile Data Connectivity"
        echo ""
        echo "usage: svc data [enable|disable]"
        echo ""
    fi
    exit 1
fi

export CLASSPATH=/system/framework/svc.jar
exec app_process /system/bin com.android.commands.svc.Svc "$@"

/system/bin/svc 文件就是 frameworks/base/cmds/svc/svc

frameworks/base/cmds/svc/svc 这个文件是在哪里编进去的呢?
frameworks/base/cmds/svc/Android.bp 文件中只有java文件的编译方法,生成的是jar包,out/target/product/k80_bsp/system/framework/svc.jar

java_binary {
    name: "svc",
    wrapper: "svc",
    srcs: ["**/*.java"],
}

./out/soong/Android-full_k80_bsp.mk 下找到了 svc 对应的module代码,但又是在哪里生成这个文件的呢?

include $(CLEAR_VARS)
LOCAL_PATH := frameworks/base/cmds/svc
LOCAL_MODULE := svc
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_PREBUILT_MODULE_FILE := frameworks/base/cmds/svc/svc
LOCAL_MODULE_TARGET_ARCH := arm
LOCAL_NOTICE_FILE := frameworks/base/cmds/svc/NOTICE
LOCAL_STRIP_MODULE := false
include $(BUILD_PREBUILT)
$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)
jar_installed_module :=
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值