1 /* 2 * Copyright 2014, 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 package com.android.managedprovisioning; 17 18 import android.accounts.Account; 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.SharedPreferences; 23 import android.os.Bundle; 24 import android.os.PersistableBundle; 25 import android.util.Xml; 26 27 import org.xmlpull.v1.XmlPullParser; 28 import org.xmlpull.v1.XmlPullParserException; 29 import org.xmlpull.v1.XmlPullParserFactory; 30 import org.xmlpull.v1.XmlSerializer; 31 32 import java.io.IOException; 33 import java.io.StringReader; 34 import java.io.StringWriter; 35 36 /** 37 * Helper class to load/save resume information from Intents into a SharedPreferences. 38 */ 39 public class IntentStore { 40 private SharedPreferences mPrefs; 41 private String mPrefsName; // Name of the file where mPrefs is stored. 42 private Context mContext; 43 private ComponentName mIntentTarget; 44 45 // Key arrays should never be null. 46 private String[] mStringKeys = new String[0]; 47 private String[] mLongKeys = new String[0]; 48 private String[] mIntKeys = new String[0]; 49 private String[] mBooleanKeys = new String[0]; 50 private String[] mPersistableBundleKeys = new String[0]; 51 private String[] mAccountKeys = new String[0]; 52 private String[] mComponentNameKeys = new String[0]; 53 54 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle"; 55 private static final String TAG_ACCOUNT = "account"; 56 private static final String ATTRIBUTE_ACCOUNT_NAME = "name"; 57 private static final String ATTRIBUTE_ACCOUNT_TYPE = "type"; 58 59 private static final String IS_SET = "isSet"; 60 IntentStore(Context context, ComponentName intentTarget, String preferencesName)61 public IntentStore(Context context, ComponentName intentTarget, String preferencesName) { 62 mContext = context; 63 mPrefsName = preferencesName; 64 mPrefs = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE); 65 mIntentTarget = intentTarget; 66 } 67 setStringKeys(String[] keys)68 public IntentStore setStringKeys(String[] keys) { 69 mStringKeys = (keys == null) ? new String[0] : keys; 70 return this; 71 } 72 setLongKeys(String[] keys)73 public IntentStore setLongKeys(String[] keys) { 74 mLongKeys = (keys == null) ? new String[0] : keys; 75 return this; 76 } 77 setIntKeys(String[] keys)78 public IntentStore setIntKeys(String[] keys) { 79 mIntKeys = (keys == null) ? new String[0] : keys; 80 return this; 81 } 82 setBooleanKeys(String[] keys)83 public IntentStore setBooleanKeys(String[] keys) { 84 mBooleanKeys = (keys == null) ? new String[0] : keys; 85 return this; 86 } 87 setAccountKeys(String[] keys)88 public IntentStore setAccountKeys(String[] keys) { 89 mAccountKeys = (keys == null) ? new String[0] : keys; 90 return this; 91 } 92 setPersistableBundleKeys(String[] keys)93 public IntentStore setPersistableBundleKeys(String[] keys) { 94 mPersistableBundleKeys = (keys == null) ? new String[0] : keys; 95 return this; 96 } 97 setComponentNameKeys(String[] keys)98 public IntentStore setComponentNameKeys(String[] keys) { 99 mComponentNameKeys = (keys == null) ? new String[0] : keys; 100 return this; 101 } 102 clear()103 public void clear() { 104 mPrefs.edit().clear().commit(); 105 } 106 save(Bundle data)107 public void save(Bundle data){ 108 SharedPreferences.Editor editor = mPrefs.edit(); 109 110 editor.clear(); 111 for (String key : mStringKeys) { 112 editor.putString(key, data.getString(key)); 113 } 114 for (String key : mLongKeys) { 115 editor.putLong(key, data.getLong(key)); 116 } 117 for (String key : mIntKeys) { 118 editor.putInt(key, data.getInt(key)); 119 } 120 for (String key : mBooleanKeys) { 121 editor.putBoolean(key, data.getBoolean(key)); 122 } 123 for (String key : mAccountKeys) { 124 Account account = (Account) data.getParcelable(key); 125 String accountString = accountToString(account); 126 if (accountString != null) { 127 editor.putString(key, accountString); 128 } 129 } 130 for (String key : mPersistableBundleKeys) { 131 132 // Cast should be guaranteed to succeed by check in the provisioning activities. 133 String bundleString = persistableBundleToString((PersistableBundle) data 134 .getParcelable(key)); 135 if (bundleString != null) { 136 editor.putString(key, bundleString); 137 } 138 } 139 for (String key : mComponentNameKeys) { 140 ComponentName cn = (ComponentName) data.getParcelable(key); 141 if (cn != null) { 142 editor.putString(key, cn.flattenToString()); 143 } 144 } 145 editor.putBoolean(IS_SET, true); 146 editor.commit(); 147 } 148 load()149 public Intent load() { 150 if (!mPrefs.getBoolean(IS_SET, false)) { 151 return null; 152 } 153 154 Intent result = new Intent(); 155 result.setComponent(mIntentTarget); 156 157 for (String key : mStringKeys) { 158 String value = mPrefs.getString(key, null); 159 if (value != null) { 160 result.putExtra(key, value); 161 } 162 } 163 for (String key : mLongKeys) { 164 if (mPrefs.contains(key)) { 165 result.putExtra(key, mPrefs.getLong(key, 0)); 166 } 167 } 168 for (String key : mIntKeys) { 169 if (mPrefs.contains(key)) { 170 result.putExtra(key, mPrefs.getInt(key, 0)); 171 } 172 } 173 for (String key : mBooleanKeys) { 174 if (mPrefs.contains(key)) { 175 result.putExtra(key, mPrefs.getBoolean(key, false)); 176 } 177 } 178 for (String key : mAccountKeys) { 179 if (mPrefs.contains(key)) { 180 Account account = stringToAccount(mPrefs.getString(key, null)); 181 if (account != null) { 182 result.putExtra(key, account); 183 } 184 } 185 } 186 for (String key : mPersistableBundleKeys) { 187 if (mPrefs.contains(key)) { 188 PersistableBundle bundle = stringToPersistableBundle(mPrefs.getString(key, null)); 189 if (bundle != null) { 190 result.putExtra(key, bundle); 191 } 192 } 193 } 194 for (String key : mComponentNameKeys) { 195 if (mPrefs.contains(key)) { 196 String st = mPrefs.getString(key, null); 197 if (st != null) { 198 result.putExtra(key, ComponentName.unflattenFromString(st)); 199 } 200 } 201 } 202 203 return result; 204 } 205 accountToString(Account account)206 private String accountToString(Account account) { 207 if (account == null) { 208 return null; 209 } 210 StringWriter writer = new StringWriter(); 211 XmlSerializer serializer = Xml.newSerializer(); 212 try { 213 serializer.setOutput(writer); 214 serializer.startDocument(null, true); 215 serializer.startTag(null, TAG_ACCOUNT); 216 serializer.attribute(null /* namespace */, ATTRIBUTE_ACCOUNT_NAME, account.name); 217 serializer.attribute(null /* namespace */, ATTRIBUTE_ACCOUNT_TYPE, account.type); 218 serializer.endTag(null, TAG_ACCOUNT); 219 serializer.endDocument(); 220 } catch (IOException e) { 221 ProvisionLogger.loge("Account could not be stored as string.", e); 222 return null; 223 } 224 225 return writer.toString(); 226 } 227 stringToAccount(String string)228 private Account stringToAccount(String string) { 229 if (string == null) { 230 return null; 231 } 232 XmlPullParserFactory factory; 233 XmlPullParser parser; 234 try { 235 factory = XmlPullParserFactory.newInstance(); 236 237 parser = factory.newPullParser(); 238 parser.setInput(new StringReader(string)); 239 240 if ((parser.next() == XmlPullParser.START_TAG) 241 && TAG_ACCOUNT.equals(parser.getName())) { 242 String name = parser.getAttributeValue(null /* namespace */, 243 ATTRIBUTE_ACCOUNT_NAME); 244 String type = parser.getAttributeValue(null /* namespace */, 245 ATTRIBUTE_ACCOUNT_TYPE); 246 if (name != null && type != null) { 247 return new Account(name, type); 248 } 249 } 250 } catch (IOException|XmlPullParserException e) { 251 ProvisionLogger.loge(e); 252 // Fall through. 253 } 254 ProvisionLogger.loge("Account could not be restored from string " + string); 255 return null; 256 } 257 persistableBundleToString(PersistableBundle bundle)258 private String persistableBundleToString(PersistableBundle bundle) { 259 if (bundle == null) { 260 return null; 261 } 262 263 StringWriter writer = new StringWriter(); 264 XmlSerializer serializer = Xml.newSerializer(); 265 try { 266 serializer.setOutput(writer); 267 serializer.startDocument(null, true); 268 serializer.startTag(null, TAG_PERSISTABLEBUNDLE); 269 bundle.saveToXml(serializer); 270 serializer.endTag(null, TAG_PERSISTABLEBUNDLE); 271 serializer.endDocument(); 272 } catch (IOException|XmlPullParserException e) { 273 ProvisionLogger.loge("Persistable bundle could not be stored as string.", e); 274 return null; 275 } 276 277 return writer.toString(); 278 } 279 stringToPersistableBundle(String string)280 private PersistableBundle stringToPersistableBundle(String string) { 281 if (string == null) { 282 return null; 283 } 284 285 XmlPullParserFactory factory; 286 XmlPullParser parser; 287 try { 288 factory = XmlPullParserFactory.newInstance(); 289 290 parser = factory.newPullParser(); 291 parser.setInput(new StringReader(string)); 292 293 if (parser.next() == XmlPullParser.START_TAG) { 294 if (TAG_PERSISTABLEBUNDLE.equals(parser.getName())) { 295 return PersistableBundle.restoreFromXml(parser); 296 } 297 } 298 } catch (IOException|XmlPullParserException e) { 299 ProvisionLogger.loge(e); 300 // Fall through. 301 } 302 ProvisionLogger.loge("Persistable bundle could not be restored from string " + string); 303 return null; 304 } 305 } 306