关键字: android, settings, cmd
20180822 tjy
转载请注明出处
Android 中有一个可执行文件settings,可以使得调试变得方便。
查看settings的代码,会有其他额外发现。
文件位置
device-name:/system/bin # ls -l settings
ls -l settings
-rwxr-xr-x 1 root shell 35 2018-08-03 04:17 settings
device-name:/system/bin #
settings用法
device-name:/ # settings
settings
Settings provider (settings) commands:
help
Print this help text.
get [--user <USER_ID> | current] NAMESPACE KEY
Retrieve the current value of KEY.
put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TAG] [default]
Change the contents of KEY to VALUE.
TAG to associate with the setting.
{default} to set as the default, case-insensitive only for global/secure namespace
delete NAMESPACE KEY
Delete the entry for KEY.
reset [--user <USER_ID> | current] NAMESPACE {PACKAGE_NAME | RESET_MODE}
Reset the global/secure table for a package with mode.
RESET_MODE is one of {untrusted_defaults, untrusted_clear, trusted_defaults}, case-insensitive
list NAMESPACE
Print all defined keys.
NAMESPACE is one of {system, secure, global}, case-insensitive
settings list命令
device-name:/ # settings list global
settings list global
adb_enabled=1
add_users_when_locked=0
airplane_mode_on=0
airplane_mode_radios=cell,bluetooth,wifi,nfc,wimax
airplane_mode_toggleable_radios=bluetooth,wifi,nfc
assisted_gps_enabled=1
att_wifi_call_enable=0
audio_safe_volume_state=3
auto_time=1
auto_time_zone=1
bluetooth_disabled_profiles=0
bluetooth_on=0
boot_count=5
call_auto_retry=0
captive_portal_mode=1
car_dock_sound=/system/media/audio/ui/Dock.ogg
car_undock_sound=/system/media/audio/ui/Undock.ogg
cdma_cell_broadcast_sms=1
data_roaming0=1
data_roaming=1
default_install_location=0
default_restrict_background_data=0
desk_dock_sound=/system/media/audio/ui/Dock.ogg
desk_undock_sound=/system/media/audio/ui/Undock.ogg
development_settings_enabled=1
device_provisioned=1
dock_audio_media_enabled=1
dock_sounds_enabled=0
dock_sounds_enabled_when_accessbility=0
emergency_affordance_needed=0
emergency_tone=0
heads_up_notifications_enabled=1
lock_sound=/system/media/audio/ui/Lock.ogg
low_battery_sound=/system/media/audio/ui/LowBattery.ogg
low_battery_sound_timeout=0
mobile_data0=1
mobile_data=1
mobile_data_always_on=0
mode_ringer=2
netstats_enabled=1
network_recommendations_enabled=0
package_verifier_enable=1
power_sounds_enabled=1
preferred_network_mode=10
set_install_location=0
stay_on_while_plugged_in=0
subscription_mode=0
theater_mode_on=0
trusted_sound=/system/media/audio/ui/Trusted.ogg
unlock_sound=/system/media/audio/ui/Unlock.ogg
usb_mass_storage_enabled=1
verifier_verify_adb_installs=0
volte_vt_enabled=1
wfc_ims_enabled=0
wfc_ims_mode=1
wifi_display_on=0
wifi_max_dhcp_retry_count=9
wifi_networks_available_notification_on=1
wifi_on=0
wifi_scan_always_enabled=0
wifi_sleep_policy=2
wifi_wakeup_available=0
wifi_wakeup_enabled=1
wireless_charging_started_sound=/system/media/audio/ui/WirelessChargingStarted.ogg
settings put和get
device-name:/ # settings get global bluetooth_on
settings get global bluetooth_on
0
device-name:/ # settings put global bluetooth_on 1
settings put global bluetooth_on 1
device-name:/ #
代码位置在frameworks/base/cmds/settings/settings,打开这个文件,发现它是一个shell,调用了cmd命令,cmd命令又在哪里呢?
//from http://androidxref.com/8.1.0_r33/xref/frameworks/base/cmds/settings/settings
#!/system/bin/sh
cmd settings "$@"
在frameworks/native/cmds/cmd/cmd.cpp中,代码如下。
cmd通过IServiceManager去实现操作。
通过看代码,cmd -l可以把service都列出来。
cmd settings是通过调用 service settings中的方法来完成的。
//from http://androidxref.com/8.1.0_r33/xref/frameworks/native/cmds/cmd/cmd.cpp
int main(int argc, char* const argv[])
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc = ProcessState::self();
// setThreadPoolMaxThreadCount(0) actually tells the kernel it's
// not allowed to spawn any additional threads, but we still spawn
// a binder thread from userspace when we call startThreadPool().
// This is safe because we only have 2 callbacks, neither of which
// block.
// See b/36066697 for rationale
proc->setThreadPoolMaxThreadCount(0);
proc->startThreadPool();
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
if (sm == NULL) {
ALOGW("Unable to get default service manager!");
aerr << "cmd: Unable to get default service manager!" << endl;
return 20;
}
if (argc == 1) {
aerr << "cmd: No service specified; use -l to list all services" << endl;
return 20;
}
if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
Vector<String16> services = sm->listServices();
services.sort(sort_func);
aout << "Currently running services:" << endl;
for (size_t i=0; i<services.size(); i++) {
sp<IBinder> service = sm->checkService(services[i]);
if (service != NULL) {
aout << " " << services[i] << endl;
}
}
return 0;
}
Vector<String16> args;
for (int i=2; i<argc; i++) {
args.add(String16(argv[i]));
}
String16 cmd = String16(argv[1]);
sp<IBinder> service = sm->checkService(cmd);
if (service == NULL) {
ALOGW("Can't find service %s", argv[1]);
aerr << "cmd: Can't find service: " << argv[1] << endl;
return 20;
}
sp<MyShellCallback> cb = new MyShellCallback();
sp<MyResultReceiver> result = new MyResultReceiver();
#if DEBUG
ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", argv[1], STDIN_FILENO, STDOUT_FILENO,
STDERR_FILENO);
#endif
// TODO: block until a result is returned to MyResultReceiver.
status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
cb, result);
if (err < 0) {
const char* errstr;
switch (err) {
case BAD_TYPE: errstr = "Bad type"; break;
case FAILED_TRANSACTION: errstr = "Failed transaction"; break;
case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;
case UNEXPECTED_NULL: errstr = "Unexpected null"; break;
default: errstr = strerror(-err); break;
}
ALOGW("Failure calling service %s: %s (%d)", argv[1], errstr, -err);
aout << "cmd: Failure calling service " << argv[1] << ": " << errstr << " ("
<< (-err) << ")" << endl;
return err;
}
cb->mActive = false;
status_t res = result->waitForResult();
#if DEBUG
ALOGD("result=%d", (int)res);
#endif
return res;
}
继续追一下IBinder::shellCommand代码,定义在frameworks/native/libs/binder/Binder.cpp。
后续补充Binder的逻辑。
//from http://androidxref.com/8.1.0_r33/xref/frameworks/native/libs/binder/Binder.cpp#65
status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver)
{
Parcel send;
Parcel reply;
send.writeFileDescriptor(in);
send.writeFileDescriptor(out);
send.writeFileDescriptor(err);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
send.writeStrongBinder(callback != NULL ? IInterface::asBinder(callback) : NULL);
send.writeStrongBinder(resultReceiver != NULL ? IInterface::asBinder(resultReceiver) : NULL);
return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}