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