blob: 3656f09c71c5fc2cd3e5ba0bdd2f148e800d80df [file] [log] [blame]
Sander Alewijnse28bffd62014-06-05 10:54:26 +01001/*
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 */
16package com.android.managedprovisioning;
17
Alexandra Gherghina7cca9272014-11-26 20:57:13 +000018import android.accounts.Account;
Sander Alewijnse28bffd62014-06-05 10:54:26 +010019import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.SharedPreferences;
Sander Alewijnse28bffd62014-06-05 10:54:26 +010023import android.os.Bundle;
Sander Alewijnsef88f7092014-08-20 16:26:09 +010024import android.os.PersistableBundle;
25import android.util.Xml;
26
Sander Alewijnsef88f7092014-08-20 16:26:09 +010027import org.xmlpull.v1.XmlPullParser;
28import org.xmlpull.v1.XmlPullParserException;
29import org.xmlpull.v1.XmlPullParserFactory;
30import org.xmlpull.v1.XmlSerializer;
Sander Alewijnse28bffd62014-06-05 10:54:26 +010031
Alexandra Gherghina7cca9272014-11-26 20:57:13 +000032import java.io.IOException;
33import java.io.StringReader;
34import java.io.StringWriter;
35
Sander Alewijnse28bffd62014-06-05 10:54:26 +010036/**
37 * Helper class to load/save resume information from Intents into a SharedPreferences.
38 */
39public class IntentStore {
40 private SharedPreferences mPrefs;
Sander Alewijnse56f71572014-06-23 16:21:33 +010041 private String mPrefsName; // Name of the file where mPrefs is stored.
42 private Context mContext;
Sander Alewijnse28bffd62014-06-05 10:54:26 +010043 private ComponentName mIntentTarget;
44
Sander Alewijnsef88f7092014-08-20 16:26:09 +010045 // 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];
Alexandra Gherghina7cca9272014-11-26 20:57:13 +000051 private String[] mAccountKeys = new String[0];
Nicolas Prevot0b447252015-03-09 14:59:02 +000052 private String[] mComponentNameKeys = new String[0];
Sander Alewijnsef88f7092014-08-20 16:26:09 +010053
54 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
Alexandra Gherghina7cca9272014-11-26 20:57:13 +000055 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";
Sander Alewijnsef88f7092014-08-20 16:26:09 +010058
Sander Alewijnse56f71572014-06-23 16:21:33 +010059 private static final String IS_SET = "isSet";
60
Sander Alewijnsef88f7092014-08-20 16:26:09 +010061 public IntentStore(Context context, ComponentName intentTarget, String preferencesName) {
Sander Alewijnse56f71572014-06-23 16:21:33 +010062 mContext = context;
63 mPrefsName = preferencesName;
Sander Alewijnse28bffd62014-06-05 10:54:26 +010064 mPrefs = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE);
Sander Alewijnse28bffd62014-06-05 10:54:26 +010065 mIntentTarget = intentTarget;
66 }
67
Sander Alewijnsef88f7092014-08-20 16:26:09 +010068 public IntentStore setStringKeys(String[] keys) {
69 mStringKeys = (keys == null) ? new String[0] : keys;
70 return this;
71 }
72
73 public IntentStore setLongKeys(String[] keys) {
74 mLongKeys = (keys == null) ? new String[0] : keys;
75 return this;
76 }
77
78 public IntentStore setIntKeys(String[] keys) {
79 mIntKeys = (keys == null) ? new String[0] : keys;
80 return this;
81 }
82
83 public IntentStore setBooleanKeys(String[] keys) {
84 mBooleanKeys = (keys == null) ? new String[0] : keys;
85 return this;
86 }
87
Alexandra Gherghina7cca9272014-11-26 20:57:13 +000088 public IntentStore setAccountKeys(String[] keys) {
89 mAccountKeys = (keys == null) ? new String[0] : keys;
90 return this;
91 }
92
Sander Alewijnsef88f7092014-08-20 16:26:09 +010093 public IntentStore setPersistableBundleKeys(String[] keys) {
94 mPersistableBundleKeys = (keys == null) ? new String[0] : keys;
95 return this;
96 }
97
Nicolas Prevot0b447252015-03-09 14:59:02 +000098 public IntentStore setComponentNameKeys(String[] keys) {
99 mComponentNameKeys = (keys == null) ? new String[0] : keys;
100 return this;
101 }
102
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100103 public void clear() {
104 mPrefs.edit().clear().commit();
105 }
106
107 public void save(Bundle data){
108 SharedPreferences.Editor editor = mPrefs.edit();
109
110 editor.clear();
Sander Alewijnse56f71572014-06-23 16:21:33 +0100111 for (String key : mStringKeys) {
112 editor.putString(key, data.getString(key));
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100113 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100114 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 }
Alexandra Gherghina7cca9272014-11-26 20:57:13 +0000123 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 }
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100130 for (String key : mPersistableBundleKeys) {
131
132 // Cast should be guaranteed to succeed by check in the provisioning activities.
Sander Alewijnsed49a6552014-09-04 10:45:29 +0100133 String bundleString = persistableBundleToString((PersistableBundle) data
134 .getParcelable(key));
135 if (bundleString != null) {
136 editor.putString(key, bundleString);
137 }
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100138 }
Nicolas Prevot0b447252015-03-09 14:59:02 +0000139 for (String key : mComponentNameKeys) {
140 ComponentName cn = (ComponentName) data.getParcelable(key);
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000141 if (cn != null) {
142 editor.putString(key, cn.flattenToString());
143 }
Nicolas Prevot0b447252015-03-09 14:59:02 +0000144 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100145 editor.putBoolean(IS_SET, true);
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100146 editor.commit();
147 }
148
149 public Intent load() {
Sander Alewijnse56f71572014-06-23 16:21:33 +0100150 if (!mPrefs.getBoolean(IS_SET, false)) {
151 return null;
152 }
153
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100154 Intent result = new Intent();
155 result.setComponent(mIntentTarget);
156
157 for (String key : mStringKeys) {
158 String value = mPrefs.getString(key, null);
Sander Alewijnse56f71572014-06-23 16:21:33 +0100159 if (value != null) {
160 result.putExtra(key, value);
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100161 }
Sander Alewijnse56f71572014-06-23 16:21:33 +0100162 }
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 }
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100177 }
Alexandra Gherghina7cca9272014-11-26 20:57:13 +0000178 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 }
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100186 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 }
Nicolas Prevot0b447252015-03-09 14:59:02 +0000194 for (String key : mComponentNameKeys) {
195 if (mPrefs.contains(key)) {
Nicolas Prevot668d65f2015-03-10 17:58:15 +0000196 String st = mPrefs.getString(key, null);
197 if (st != null) {
198 result.putExtra(key, ComponentName.unflattenFromString(st));
199 }
Nicolas Prevot0b447252015-03-09 14:59:02 +0000200 }
201 }
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100202
203 return result;
204 }
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100205
Alexandra Gherghina7cca9272014-11-26 20:57:13 +0000206 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
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
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100258 private String persistableBundleToString(PersistableBundle bundle) {
Sander Alewijnsed49a6552014-09-04 10:45:29 +0100259 if (bundle == null) {
260 return null;
261 }
262
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100263 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
280 private PersistableBundle stringToPersistableBundle(String string) {
Sander Alewijnsed49a6552014-09-04 10:45:29 +0100281 if (string == null) {
282 return null;
283 }
284
Sander Alewijnsef88f7092014-08-20 16:26:09 +0100285 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 }
Sander Alewijnse28bffd62014-06-05 10:54:26 +0100305}