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