1af75948cddd40a0fde5af051b700306744eae64cChristopher Tate/* 2af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * Copyright (C) 2012 The Android Open Source Project 3af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * 4af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License"); 5af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * you may not use this file except in compliance with the License. 6af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * You may obtain a copy of the License at 7af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * 8af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * http://www.apache.org/licenses/LICENSE-2.0 9af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * 10af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * Unless required by applicable law or agreed to in writing, software 11af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS, 12af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * See the License for the specific language governing permissions and 14af75948cddd40a0fde5af051b700306744eae64cChristopher Tate * limitations under the License. 15af75948cddd40a0fde5af051b700306744eae64cChristopher Tate */ 16af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 17af75948cddd40a0fde5af051b700306744eae64cChristopher Tatepackage com.android.commands.settings; 18af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 19af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.app.ActivityManagerNative; 20af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.app.IActivityManager; 21af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.app.IActivityManager.ContentProviderHolder; 22af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.content.IContentProvider; 23af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.os.Binder; 24af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.os.Bundle; 25af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.os.IBinder; 26af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.os.RemoteException; 27af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.os.UserHandle; 28af75948cddd40a0fde5af051b700306744eae64cChristopher Tateimport android.provider.Settings; 29af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 30af75948cddd40a0fde5af051b700306744eae64cChristopher Tatepublic final class SettingsCmd { 31af75948cddd40a0fde5af051b700306744eae64cChristopher Tate static final String TAG = "settings"; 32af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 33af75948cddd40a0fde5af051b700306744eae64cChristopher Tate enum CommandVerb { 34af75948cddd40a0fde5af051b700306744eae64cChristopher Tate UNSPECIFIED, 35af75948cddd40a0fde5af051b700306744eae64cChristopher Tate GET, 36af75948cddd40a0fde5af051b700306744eae64cChristopher Tate PUT 37af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 38af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 39af75948cddd40a0fde5af051b700306744eae64cChristopher Tate static String[] mArgs; 40af75948cddd40a0fde5af051b700306744eae64cChristopher Tate int mNextArg; 41af75948cddd40a0fde5af051b700306744eae64cChristopher Tate int mUser = -1; // unspecified 42af75948cddd40a0fde5af051b700306744eae64cChristopher Tate CommandVerb mVerb = CommandVerb.UNSPECIFIED; 43af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String mTable = null; 44af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String mKey = null; 45af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String mValue = null; 46af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 47af75948cddd40a0fde5af051b700306744eae64cChristopher Tate public static void main(String[] args) { 48af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (args == null || args.length < 3) { 49af75948cddd40a0fde5af051b700306744eae64cChristopher Tate printUsage(); 50af75948cddd40a0fde5af051b700306744eae64cChristopher Tate return; 51af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 52af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 53af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mArgs = args; 54af75948cddd40a0fde5af051b700306744eae64cChristopher Tate try { 55af75948cddd40a0fde5af051b700306744eae64cChristopher Tate new SettingsCmd().run(); 56af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } catch (Exception e) { 57af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Unable to run settings command"); 58af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 59af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 60af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 61af75948cddd40a0fde5af051b700306744eae64cChristopher Tate public void run() { 62af75948cddd40a0fde5af051b700306744eae64cChristopher Tate boolean valid = false; 63af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String arg; 64af75948cddd40a0fde5af051b700306744eae64cChristopher Tate try { 65af75948cddd40a0fde5af051b700306744eae64cChristopher Tate while ((arg = nextArg()) != null) { 66af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if ("--user".equals(arg)) { 67af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (mUser != -1) { 68af75948cddd40a0fde5af051b700306744eae64cChristopher Tate // --user specified more than once; invalid 69af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 70af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 71af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mUser = Integer.parseInt(nextArg()); 72af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else if (mVerb == CommandVerb.UNSPECIFIED) { 73af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if ("get".equalsIgnoreCase(arg)) { 74af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mVerb = CommandVerb.GET; 75af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else if ("put".equalsIgnoreCase(arg)) { 76af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mVerb = CommandVerb.PUT; 77af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else { 78af75948cddd40a0fde5af051b700306744eae64cChristopher Tate // invalid 79af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Invalid command: " + arg); 80af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 81af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 82af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else if (mTable == null) { 83af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (!"system".equalsIgnoreCase(arg) 84af75948cddd40a0fde5af051b700306744eae64cChristopher Tate && !"secure".equalsIgnoreCase(arg) 85af75948cddd40a0fde5af051b700306744eae64cChristopher Tate && !"global".equalsIgnoreCase(arg)) { 86af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Invalid namespace '" + arg + "'"); 87af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; // invalid 88af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 89af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mTable = arg.toLowerCase(); 90af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else if (mVerb == CommandVerb.GET) { 91af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mKey = arg; 92af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (mNextArg >= mArgs.length) { 93af75948cddd40a0fde5af051b700306744eae64cChristopher Tate valid = true; 94af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else { 95af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Too many arguments"); 96af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 97af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 98af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else if (mKey == null) { 99af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mKey = arg; 100af75948cddd40a0fde5af051b700306744eae64cChristopher Tate // keep going; there's another PUT arg 101af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else { // PUT, final arg 102af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mValue = arg; 103af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (mNextArg >= mArgs.length) { 104af75948cddd40a0fde5af051b700306744eae64cChristopher Tate valid = true; 105af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else { 106af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Too many arguments"); 107af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 108af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 109af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 110af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 111af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } catch (Exception e) { 112af75948cddd40a0fde5af051b700306744eae64cChristopher Tate valid = false; 113af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 114af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 115af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (valid) { 116af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (mUser < 0) { 117af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mUser = UserHandle.USER_OWNER; 118af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 119af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 120af75948cddd40a0fde5af051b700306744eae64cChristopher Tate try { 121af75948cddd40a0fde5af051b700306744eae64cChristopher Tate IActivityManager activityManager = ActivityManagerNative.getDefault(); 122af75948cddd40a0fde5af051b700306744eae64cChristopher Tate IContentProvider provider = null; 123af75948cddd40a0fde5af051b700306744eae64cChristopher Tate IBinder token = new Binder(); 124af75948cddd40a0fde5af051b700306744eae64cChristopher Tate try { 125af75948cddd40a0fde5af051b700306744eae64cChristopher Tate ContentProviderHolder holder = activityManager.getContentProviderExternal( 126af75948cddd40a0fde5af051b700306744eae64cChristopher Tate "settings", UserHandle.USER_OWNER, token); 127af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (holder == null) { 128af75948cddd40a0fde5af051b700306744eae64cChristopher Tate throw new IllegalStateException("Could not find settings provider"); 129af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 130af75948cddd40a0fde5af051b700306744eae64cChristopher Tate provider = holder.provider; 131af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 132af75948cddd40a0fde5af051b700306744eae64cChristopher Tate switch (mVerb) { 133af75948cddd40a0fde5af051b700306744eae64cChristopher Tate case GET: 134af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.out.println(getForUser(provider, mUser, mTable, mKey)); 135af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 136af75948cddd40a0fde5af051b700306744eae64cChristopher Tate case PUT: 137af75948cddd40a0fde5af051b700306744eae64cChristopher Tate putForUser(provider, mUser, mTable, mKey, mValue); 138af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 139af75948cddd40a0fde5af051b700306744eae64cChristopher Tate default: 140af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Unspecified command"); 141af75948cddd40a0fde5af051b700306744eae64cChristopher Tate break; 142af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 143af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 144af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } finally { 145af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (provider != null) { 146af75948cddd40a0fde5af051b700306744eae64cChristopher Tate activityManager.removeContentProviderExternal("settings", token); 147af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 148af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 149af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } catch (Exception e) { 150af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Error while accessing settings provider"); 151af75948cddd40a0fde5af051b700306744eae64cChristopher Tate e.printStackTrace(); 152af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 153af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 154af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } else { 155af75948cddd40a0fde5af051b700306744eae64cChristopher Tate printUsage(); 156af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 157af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 158af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 159af75948cddd40a0fde5af051b700306744eae64cChristopher Tate private String nextArg() { 160af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (mNextArg >= mArgs.length) { 161af75948cddd40a0fde5af051b700306744eae64cChristopher Tate return null; 162af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 163af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String arg = mArgs[mNextArg]; 164af75948cddd40a0fde5af051b700306744eae64cChristopher Tate mNextArg++; 165af75948cddd40a0fde5af051b700306744eae64cChristopher Tate return arg; 166af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 167af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 168af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String getForUser(IContentProvider provider, int userHandle, 169af75948cddd40a0fde5af051b700306744eae64cChristopher Tate final String table, final String key) { 170af75948cddd40a0fde5af051b700306744eae64cChristopher Tate final String callGetCommand; 171af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM; 172af75948cddd40a0fde5af051b700306744eae64cChristopher Tate else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE; 173af75948cddd40a0fde5af051b700306744eae64cChristopher Tate else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL; 174af75948cddd40a0fde5af051b700306744eae64cChristopher Tate else { 175af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Invalid table; no put performed"); 176af75948cddd40a0fde5af051b700306744eae64cChristopher Tate throw new IllegalArgumentException("Invalid table " + table); 177af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 178af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 179af75948cddd40a0fde5af051b700306744eae64cChristopher Tate String result = null; 180af75948cddd40a0fde5af051b700306744eae64cChristopher Tate try { 181af75948cddd40a0fde5af051b700306744eae64cChristopher Tate Bundle arg = new Bundle(); 182af75948cddd40a0fde5af051b700306744eae64cChristopher Tate arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle); 183af75948cddd40a0fde5af051b700306744eae64cChristopher Tate Bundle b = provider.call(callGetCommand, key, arg); 184af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if (b != null) { 185af75948cddd40a0fde5af051b700306744eae64cChristopher Tate result = b.getPairValue(); 186af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 187af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } catch (RemoteException e) { 188af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Can't read key " + key + " in " + table + " for user " + userHandle); 189af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 190af75948cddd40a0fde5af051b700306744eae64cChristopher Tate return result; 191af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 192af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 193af75948cddd40a0fde5af051b700306744eae64cChristopher Tate void putForUser(IContentProvider provider, int userHandle, 194af75948cddd40a0fde5af051b700306744eae64cChristopher Tate final String table, final String key, final String value) { 195af75948cddd40a0fde5af051b700306744eae64cChristopher Tate final String callPutCommand; 196af75948cddd40a0fde5af051b700306744eae64cChristopher Tate if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM; 197af75948cddd40a0fde5af051b700306744eae64cChristopher Tate else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE; 198af75948cddd40a0fde5af051b700306744eae64cChristopher Tate else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL; 199af75948cddd40a0fde5af051b700306744eae64cChristopher Tate else { 200af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Invalid table; no put performed"); 201af75948cddd40a0fde5af051b700306744eae64cChristopher Tate return; 202af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 203af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 204af75948cddd40a0fde5af051b700306744eae64cChristopher Tate try { 205af75948cddd40a0fde5af051b700306744eae64cChristopher Tate Bundle arg = new Bundle(); 206af75948cddd40a0fde5af051b700306744eae64cChristopher Tate arg.putString(Settings.NameValueTable.VALUE, value); 207af75948cddd40a0fde5af051b700306744eae64cChristopher Tate arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle); 208af75948cddd40a0fde5af051b700306744eae64cChristopher Tate provider.call(callPutCommand, key, arg); 209af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } catch (RemoteException e) { 210af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("Can't set key " + key + " in " + table + " for user " + userHandle); 211af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 212af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 213af75948cddd40a0fde5af051b700306744eae64cChristopher Tate 214af75948cddd40a0fde5af051b700306744eae64cChristopher Tate private static void printUsage() { 215af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("usage: settings [--user NUM] get namespace key"); 216af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println(" settings [--user NUM] put namespace key value"); 217af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive"); 218af75948cddd40a0fde5af051b700306744eae64cChristopher Tate System.err.println("If '--user NUM' is not given, the operations are performed on the owner user."); 219af75948cddd40a0fde5af051b700306744eae64cChristopher Tate } 220af75948cddd40a0fde5af051b700306744eae64cChristopher Tate} 221