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
17package com.android.commands.settings;
18
19import android.app.ActivityManagerNative;
20import android.app.IActivityManager;
21import android.app.IActivityManager.ContentProviderHolder;
22import android.content.IContentProvider;
23import android.os.Binder;
24import android.os.Bundle;
25import android.os.IBinder;
26import android.os.RemoteException;
27import android.os.UserHandle;
28import android.provider.Settings;
29
30public 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}
221