1 /* 2 * Copyright (C) 2016 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 17 package com.android.phone.vvm.omtp; 18 19 import android.annotation.Nullable; 20 import android.content.res.Resources; 21 import android.os.PersistableBundle; 22 import android.util.ArrayMap; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 import com.android.phone.R; 26 import com.android.phone.vvm.omtp.utils.XmlUtils; 27 28 import org.xmlpull.v1.XmlPullParser; 29 import org.xmlpull.v1.XmlPullParserException; 30 31 import java.io.IOException; 32 import java.util.ArrayList; 33 import java.util.Map; 34 import java.util.Map.Entry; 35 36 /** 37 * Load and caches telephony vvm config from res/xml/vvm_config.xml 38 */ 39 public class TelephonyVvmConfigManager { 40 41 private static final String TAG = "TelephonyVvmCfgMgr"; 42 43 private static final boolean USE_DEBUG_CONFIG = false; //STOPSHIP if true 44 45 private static final String TAG_PERSISTABLEMAP = "pbundle_as_map"; 46 47 static final String KEY_MCCMNC = "mccmnc"; 48 49 private static Map<String, PersistableBundle> sCachedConfigs; 50 51 private final Map<String, PersistableBundle> mConfigs; 52 53 public TelephonyVvmConfigManager(Resources resources) { 54 if (sCachedConfigs == null) { 55 sCachedConfigs = loadConfigs(resources.getXml(R.xml.vvm_config)); 56 } 57 mConfigs = sCachedConfigs; 58 } 59 60 @VisibleForTesting 61 TelephonyVvmConfigManager(XmlPullParser parser) { 62 mConfigs = loadConfigs(parser); 63 } 64 65 @Nullable 66 public PersistableBundle getConfig(String mccMnc) { 67 if (USE_DEBUG_CONFIG) { 68 return mConfigs.get("TEST"); 69 } 70 return mConfigs.get(mccMnc); 71 } 72 73 private static Map<String, PersistableBundle> loadConfigs(XmlPullParser parser) { 74 Map<String, PersistableBundle> configs = new ArrayMap<>(); 75 try { 76 ArrayList list = readBundleList(parser); 77 for (Object object : list) { 78 if (!(object instanceof PersistableBundle)) { 79 throw new IllegalArgumentException("PersistableBundle expected, got " + object); 80 } 81 PersistableBundle bundle = (PersistableBundle) object; 82 String[] mccMncs = bundle.getStringArray(KEY_MCCMNC); 83 if (mccMncs == null) { 84 throw new IllegalArgumentException("MCCMNC is null"); 85 } 86 for (String mccMnc : mccMncs) { 87 configs.put(mccMnc, bundle); 88 } 89 } 90 } catch (IOException | XmlPullParserException e) { 91 throw new RuntimeException(e); 92 } 93 return configs; 94 } 95 96 @Nullable 97 public static ArrayList readBundleList(XmlPullParser in) throws IOException, 98 XmlPullParserException { 99 final int outerDepth = in.getDepth(); 100 int event; 101 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && 102 (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) { 103 if (event == XmlPullParser.START_TAG) { 104 final String startTag = in.getName(); 105 final String[] tagName = new String[1]; 106 in.next(); 107 return XmlUtils.readThisListXml(in, startTag, tagName, 108 new MyReadMapCallback(), false); 109 } 110 } 111 return null; 112 } 113 114 public static PersistableBundle restoreFromXml(XmlPullParser in) throws IOException, 115 XmlPullParserException { 116 final int outerDepth = in.getDepth(); 117 final String startTag = in.getName(); 118 final String[] tagName = new String[1]; 119 int event; 120 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && 121 (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) { 122 if (event == XmlPullParser.START_TAG) { 123 ArrayMap<String, ?> map = 124 XmlUtils.readThisArrayMapXml(in, startTag, tagName, 125 new MyReadMapCallback()); 126 PersistableBundle result = new PersistableBundle(); 127 for (Entry<String, ?> entry : map.entrySet()) { 128 Object value = entry.getValue(); 129 if (value instanceof Integer) { 130 result.putInt(entry.getKey(), (int) value); 131 } else if (value instanceof Boolean) { 132 result.putBoolean(entry.getKey(), (boolean) value); 133 } else if (value instanceof String) { 134 result.putString(entry.getKey(), (String) value); 135 } else if (value instanceof String[]) { 136 result.putStringArray(entry.getKey(), (String[]) value); 137 } else if (value instanceof PersistableBundle) { 138 result.putPersistableBundle(entry.getKey(), (PersistableBundle) value); 139 } 140 } 141 return result; 142 } 143 } 144 return PersistableBundle.EMPTY; 145 } 146 147 static class MyReadMapCallback implements XmlUtils.ReadMapCallback { 148 149 @Override 150 public Object readThisUnknownObjectXml(XmlPullParser in, String tag) 151 throws XmlPullParserException, IOException { 152 if (TAG_PERSISTABLEMAP.equals(tag)) { 153 return restoreFromXml(in); 154 } 155 throw new XmlPullParserException("Unknown tag=" + tag); 156 } 157 } 158 } 159