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 */ 16package com.android.managedprovisioning; 17 18import android.content.ComponentName; 19import android.content.Context; 20import android.content.Intent; 21import android.content.SharedPreferences; 22 23import android.os.Bundle; 24import android.os.PersistableBundle; 25import android.util.Xml; 26 27import java.io.IOException; 28import java.io.StringReader; 29import java.io.StringWriter; 30 31import org.xmlpull.v1.XmlPullParser; 32import org.xmlpull.v1.XmlPullParserException; 33import org.xmlpull.v1.XmlPullParserFactory; 34import org.xmlpull.v1.XmlSerializer; 35 36/** 37 * Helper class to load/save resume information from Intents into a SharedPreferences. 38 */ 39public 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 52 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle"; 53 54 private static final String IS_SET = "isSet"; 55 56 public IntentStore(Context context, ComponentName intentTarget, String preferencesName) { 57 mContext = context; 58 mPrefsName = preferencesName; 59 mPrefs = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE); 60 mIntentTarget = intentTarget; 61 } 62 63 public IntentStore setStringKeys(String[] keys) { 64 mStringKeys = (keys == null) ? new String[0] : keys; 65 return this; 66 } 67 68 public IntentStore setLongKeys(String[] keys) { 69 mLongKeys = (keys == null) ? new String[0] : keys; 70 return this; 71 } 72 73 public IntentStore setIntKeys(String[] keys) { 74 mIntKeys = (keys == null) ? new String[0] : keys; 75 return this; 76 } 77 78 public IntentStore setBooleanKeys(String[] keys) { 79 mBooleanKeys = (keys == null) ? new String[0] : keys; 80 return this; 81 } 82 83 public IntentStore setPersistableBundleKeys(String[] keys) { 84 mPersistableBundleKeys = (keys == null) ? new String[0] : keys; 85 return this; 86 } 87 88 public void clear() { 89 mPrefs.edit().clear().commit(); 90 } 91 92 public void save(Bundle data){ 93 SharedPreferences.Editor editor = mPrefs.edit(); 94 95 editor.clear(); 96 for (String key : mStringKeys) { 97 editor.putString(key, data.getString(key)); 98 } 99 for (String key : mLongKeys) { 100 editor.putLong(key, data.getLong(key)); 101 } 102 for (String key : mIntKeys) { 103 editor.putInt(key, data.getInt(key)); 104 } 105 for (String key : mBooleanKeys) { 106 editor.putBoolean(key, data.getBoolean(key)); 107 } 108 for (String key : mPersistableBundleKeys) { 109 110 // Cast should be guaranteed to succeed by check in the provisioning activities. 111 String bundleString = persistableBundleToString((PersistableBundle) data 112 .getParcelable(key)); 113 if (bundleString != null) { 114 editor.putString(key, bundleString); 115 } 116 } 117 editor.putBoolean(IS_SET, true); 118 editor.commit(); 119 } 120 121 public Intent load() { 122 if (!mPrefs.getBoolean(IS_SET, false)) { 123 return null; 124 } 125 126 Intent result = new Intent(); 127 result.setComponent(mIntentTarget); 128 129 for (String key : mStringKeys) { 130 String value = mPrefs.getString(key, null); 131 if (value != null) { 132 result.putExtra(key, value); 133 } 134 } 135 for (String key : mLongKeys) { 136 if (mPrefs.contains(key)) { 137 result.putExtra(key, mPrefs.getLong(key, 0)); 138 } 139 } 140 for (String key : mIntKeys) { 141 if (mPrefs.contains(key)) { 142 result.putExtra(key, mPrefs.getInt(key, 0)); 143 } 144 } 145 for (String key : mBooleanKeys) { 146 if (mPrefs.contains(key)) { 147 result.putExtra(key, mPrefs.getBoolean(key, false)); 148 } 149 } 150 for (String key : mPersistableBundleKeys) { 151 if (mPrefs.contains(key)) { 152 PersistableBundle bundle = stringToPersistableBundle(mPrefs.getString(key, null)); 153 if (bundle != null) { 154 result.putExtra(key, bundle); 155 } 156 } 157 } 158 159 return result; 160 } 161 162 private String persistableBundleToString(PersistableBundle bundle) { 163 if (bundle == null) { 164 return null; 165 } 166 167 StringWriter writer = new StringWriter(); 168 XmlSerializer serializer = Xml.newSerializer(); 169 try { 170 serializer.setOutput(writer); 171 serializer.startDocument(null, true); 172 serializer.startTag(null, TAG_PERSISTABLEBUNDLE); 173 bundle.saveToXml(serializer); 174 serializer.endTag(null, TAG_PERSISTABLEBUNDLE); 175 serializer.endDocument(); 176 } catch (IOException|XmlPullParserException e) { 177 ProvisionLogger.loge("Persistable bundle could not be stored as string.", e); 178 return null; 179 } 180 181 return writer.toString(); 182 } 183 184 private PersistableBundle stringToPersistableBundle(String string) { 185 if (string == null) { 186 return null; 187 } 188 189 XmlPullParserFactory factory; 190 XmlPullParser parser; 191 try { 192 factory = XmlPullParserFactory.newInstance(); 193 194 parser = factory.newPullParser(); 195 parser.setInput(new StringReader(string)); 196 197 if (parser.next() == XmlPullParser.START_TAG) { 198 if (TAG_PERSISTABLEBUNDLE.equals(parser.getName())) { 199 return PersistableBundle.restoreFromXml(parser); 200 } 201 } 202 } catch (IOException|XmlPullParserException e) { 203 ProvisionLogger.loge(e); 204 // Fall through. 205 } 206 ProvisionLogger.loge("Persistable bundle could not be restored from string " + string); 207 return null; 208 } 209} 210