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