Skip to content

Commit af75948

Browse files
author
Christopher Tate
committed
New command line tool: "settings"
Because the usual content provider interface doesn't allow specification of the target user under which to perform settings reads/writes, this CL introduces a new command line app specifically for that. Usage: settings [--user num] get namespace key settings [--user num] put namespace key value If a --user argument is not given, the owner user is targetted. Bug 7299066 Change-Id: I73108bb76b04fad133cc4e0f218d64490de549f1
1 parent bd03f5a commit af75948

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed

cmds/settings/Android.mk

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2011 The Android Open Source Project
2+
#
3+
LOCAL_PATH:= $(call my-dir)
4+
include $(CLEAR_VARS)
5+
6+
LOCAL_SRC_FILES := $(call all-subdir-java-files)
7+
LOCAL_MODULE := settings
8+
LOCAL_MODULE_TAGS := optional
9+
include $(BUILD_JAVA_LIBRARY)
10+
11+
include $(CLEAR_VARS)
12+
LOCAL_MODULE := settings
13+
LOCAL_SRC_FILES := settings
14+
LOCAL_MODULE_CLASS := EXECUTABLES
15+
LOCAL_MODULE_TAGS := optional
16+
include $(BUILD_PREBUILT)
17+
18+

cmds/settings/settings

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Script to start "settings" on the device
2+
#
3+
base=/system
4+
export CLASSPATH=$base/framework/settings.jar
5+
exec app_process $base/bin com.android.commands.settings.SettingsCmd "$@"
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/*
2+
* Copyright (C) 2012 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 com.android.commands.settings;
18+
19+
import android.app.ActivityManagerNative;
20+
import android.app.IActivityManager;
21+
import android.app.IActivityManager.ContentProviderHolder;
22+
import android.content.IContentProvider;
23+
import android.os.Binder;
24+
import android.os.Bundle;
25+
import android.os.IBinder;
26+
import android.os.RemoteException;
27+
import android.os.UserHandle;
28+
import android.provider.Settings;
29+
30+
public final class SettingsCmd {
31+
static final String TAG = "settings";
32+
33+
enum CommandVerb {
34+
UNSPECIFIED,
35+
GET,
36+
PUT
37+
}
38+
39+
static String[] mArgs;
40+
int mNextArg;
41+
int mUser = -1; // unspecified
42+
CommandVerb mVerb = CommandVerb.UNSPECIFIED;
43+
String mTable = null;
44+
String mKey = null;
45+
String mValue = null;
46+
47+
public static void main(String[] args) {
48+
if (args == null || args.length < 3) {
49+
printUsage();
50+
return;
51+
}
52+
53+
mArgs = args;
54+
try {
55+
new SettingsCmd().run();
56+
} catch (Exception e) {
57+
System.err.println("Unable to run settings command");
58+
}
59+
}
60+
61+
public void run() {
62+
boolean valid = false;
63+
String arg;
64+
try {
65+
while ((arg = nextArg()) != null) {
66+
if ("--user".equals(arg)) {
67+
if (mUser != -1) {
68+
// --user specified more than once; invalid
69+
break;
70+
}
71+
mUser = Integer.parseInt(nextArg());
72+
} else if (mVerb == CommandVerb.UNSPECIFIED) {
73+
if ("get".equalsIgnoreCase(arg)) {
74+
mVerb = CommandVerb.GET;
75+
} else if ("put".equalsIgnoreCase(arg)) {
76+
mVerb = CommandVerb.PUT;
77+
} else {
78+
// invalid
79+
System.err.println("Invalid command: " + arg);
80+
break;
81+
}
82+
} else if (mTable == null) {
83+
if (!"system".equalsIgnoreCase(arg)
84+
&& !"secure".equalsIgnoreCase(arg)
85+
&& !"global".equalsIgnoreCase(arg)) {
86+
System.err.println("Invalid namespace '" + arg + "'");
87+
break; // invalid
88+
}
89+
mTable = arg.toLowerCase();
90+
} else if (mVerb == CommandVerb.GET) {
91+
mKey = arg;
92+
if (mNextArg >= mArgs.length) {
93+
valid = true;
94+
} else {
95+
System.err.println("Too many arguments");
96+
}
97+
break;
98+
} else if (mKey == null) {
99+
mKey = arg;
100+
// keep going; there's another PUT arg
101+
} else { // PUT, final arg
102+
mValue = arg;
103+
if (mNextArg >= mArgs.length) {
104+
valid = true;
105+
} else {
106+
System.err.println("Too many arguments");
107+
}
108+
break;
109+
}
110+
}
111+
} catch (Exception e) {
112+
valid = false;
113+
}
114+
115+
if (valid) {
116+
if (mUser < 0) {
117+
mUser = UserHandle.USER_OWNER;
118+
}
119+
120+
try {
121+
IActivityManager activityManager = ActivityManagerNative.getDefault();
122+
IContentProvider provider = null;
123+
IBinder token = new Binder();
124+
try {
125+
ContentProviderHolder holder = activityManager.getContentProviderExternal(
126+
"settings", UserHandle.USER_OWNER, token);
127+
if (holder == null) {
128+
throw new IllegalStateException("Could not find settings provider");
129+
}
130+
provider = holder.provider;
131+
132+
switch (mVerb) {
133+
case GET:
134+
System.out.println(getForUser(provider, mUser, mTable, mKey));
135+
break;
136+
case PUT:
137+
putForUser(provider, mUser, mTable, mKey, mValue);
138+
break;
139+
default:
140+
System.err.println("Unspecified command");
141+
break;
142+
}
143+
144+
} finally {
145+
if (provider != null) {
146+
activityManager.removeContentProviderExternal("settings", token);
147+
}
148+
}
149+
} catch (Exception e) {
150+
System.err.println("Error while accessing settings provider");
151+
e.printStackTrace();
152+
}
153+
154+
} else {
155+
printUsage();
156+
}
157+
}
158+
159+
private String nextArg() {
160+
if (mNextArg >= mArgs.length) {
161+
return null;
162+
}
163+
String arg = mArgs[mNextArg];
164+
mNextArg++;
165+
return arg;
166+
}
167+
168+
String getForUser(IContentProvider provider, int userHandle,
169+
final String table, final String key) {
170+
final String callGetCommand;
171+
if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
172+
else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
173+
else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
174+
else {
175+
System.err.println("Invalid table; no put performed");
176+
throw new IllegalArgumentException("Invalid table " + table);
177+
}
178+
179+
String result = null;
180+
try {
181+
Bundle arg = new Bundle();
182+
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
183+
Bundle b = provider.call(callGetCommand, key, arg);
184+
if (b != null) {
185+
result = b.getPairValue();
186+
}
187+
} catch (RemoteException e) {
188+
System.err.println("Can't read key " + key + " in " + table + " for user " + userHandle);
189+
}
190+
return result;
191+
}
192+
193+
void putForUser(IContentProvider provider, int userHandle,
194+
final String table, final String key, final String value) {
195+
final String callPutCommand;
196+
if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
197+
else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
198+
else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
199+
else {
200+
System.err.println("Invalid table; no put performed");
201+
return;
202+
}
203+
204+
try {
205+
Bundle arg = new Bundle();
206+
arg.putString(Settings.NameValueTable.VALUE, value);
207+
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
208+
provider.call(callPutCommand, key, arg);
209+
} catch (RemoteException e) {
210+
System.err.println("Can't set key " + key + " in " + table + " for user " + userHandle);
211+
}
212+
}
213+
214+
private static void printUsage() {
215+
System.err.println("usage: settings [--user NUM] get namespace key");
216+
System.err.println(" settings [--user NUM] put namespace key value");
217+
System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive");
218+
System.err.println("If '--user NUM' is not given, the operations are performed on the owner user.");
219+
}
220+
}

0 commit comments

Comments
 (0)