1 /* 2 * Copyright (C) 2020 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.server.wifi; 18 19 import android.annotation.NonNull; 20 import android.util.Log; 21 22 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; 23 import com.android.server.wifi.util.XmlUtil; 24 25 import org.xmlpull.v1.XmlPullParser; 26 import org.xmlpull.v1.XmlPullParserException; 27 import org.xmlpull.v1.XmlSerializer; 28 29 import java.io.IOException; 30 import java.util.HashMap; 31 import java.util.Map; 32 33 /** 34 * This class performs serialization and parsing of XML data block that contain the map of carrier 35 * Wi-Fi offloading settings info. 36 */ 37 public class WifiCarrierInfoStoreManagerData implements WifiConfigStore.StoreData { 38 private static final String TAG = "WifiCarrierInfoStoreManagerData"; 39 private static final String XML_TAG_SECTION_HEADER = 40 "WifiCarrierInfoStoreManagerDataStores"; 41 private static final String XML_TAG_MERGED_CARRIER_NETWORK_OFFLOAD_MAP = 42 "MergedCarrierNetworkOffloadMap"; 43 private static final String XML_TAG_UNMERGED_CARRIER_NETWORK_OFFLOAD_MAP = 44 "UnmergedCarrierNetworkOffloadMap"; 45 46 /** 47 * Interface define the data source for the carrier IMSI protection exemption map store data. 48 */ 49 public interface DataSource { 50 51 /** 52 * Retrieve the merged carrier network offload map from the data source to serialize to 53 * disk. 54 */ toSerializeMergedCarrierNetworkOffloadMap()55 Map<Integer, Boolean> toSerializeMergedCarrierNetworkOffloadMap(); 56 57 /** 58 * Retrieve the unmerged carrier network offload map from the data source to serialize to 59 * disk. 60 */ toSerializeUnmergedCarrierNetworkOffloadMap()61 Map<Integer, Boolean> toSerializeUnmergedCarrierNetworkOffloadMap(); 62 63 /** 64 * Should be called when serialize is completed. 65 */ serializeComplete()66 void serializeComplete(); 67 68 69 /** 70 * Set the merged carrier network offload map in the data source after deserialize them 71 * from disk. 72 */ fromMergedCarrierNetworkOffloadMapDeserialized( Map<Integer, Boolean> carrierOffloadMap)73 void fromMergedCarrierNetworkOffloadMapDeserialized( 74 Map<Integer, Boolean> carrierOffloadMap); 75 76 /** 77 * Set the unmerged carrier network offload map in the data source after serializing them 78 * from disk. 79 */ fromUnmergedCarrierNetworkOffloadMapDeserialized( Map<Integer, Boolean> subscriptionOffloadMap)80 void fromUnmergedCarrierNetworkOffloadMapDeserialized( 81 Map<Integer, Boolean> subscriptionOffloadMap); 82 83 /** 84 * Clear internal data structure in preparation for user switch or initial store read. 85 */ reset()86 void reset(); 87 88 /** 89 * Indicates whether there is new data to serialize. 90 */ hasNewDataToSerialize()91 boolean hasNewDataToSerialize(); 92 } 93 94 private final DataSource mDataSource; 95 96 /** 97 * Set the data source fot store data. 98 */ WifiCarrierInfoStoreManagerData(@onNull DataSource dataSource)99 public WifiCarrierInfoStoreManagerData(@NonNull DataSource dataSource) { 100 mDataSource = dataSource; 101 } 102 103 @Override serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil)104 public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil) 105 throws XmlPullParserException, IOException { 106 XmlUtil.writeNextValue(out, XML_TAG_MERGED_CARRIER_NETWORK_OFFLOAD_MAP, 107 integerMapToStringMap(mDataSource.toSerializeMergedCarrierNetworkOffloadMap())); 108 XmlUtil.writeNextValue(out, XML_TAG_UNMERGED_CARRIER_NETWORK_OFFLOAD_MAP, 109 integerMapToStringMap(mDataSource.toSerializeUnmergedCarrierNetworkOffloadMap())); 110 mDataSource.serializeComplete(); 111 } 112 113 @Override deserializeData(XmlPullParser in, int outerTagDepth, int version, WifiConfigStoreEncryptionUtil encryptionUtil)114 public void deserializeData(XmlPullParser in, int outerTagDepth, int version, 115 WifiConfigStoreEncryptionUtil encryptionUtil) 116 throws XmlPullParserException, IOException { 117 mDataSource.reset(); 118 if (in != null) { 119 parseWifiCarrierInfoStoreMaps(in, outerTagDepth); 120 } 121 } 122 parseWifiCarrierInfoStoreMaps(XmlPullParser in, int outerTagDepth)123 private void parseWifiCarrierInfoStoreMaps(XmlPullParser in, 124 int outerTagDepth) 125 throws XmlPullParserException, IOException { 126 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 127 String[] valueName = new String[1]; 128 Object value = XmlUtil.readCurrentValue(in, valueName); 129 if (valueName[0] == null) { 130 throw new XmlPullParserException("Missing value name"); 131 } 132 switch (valueName[0]) { 133 case XML_TAG_MERGED_CARRIER_NETWORK_OFFLOAD_MAP: 134 if (value instanceof Map) { 135 mDataSource.fromMergedCarrierNetworkOffloadMapDeserialized( 136 stringMapToIntegerMap((Map<String, Boolean>) value)); 137 } 138 break; 139 case XML_TAG_UNMERGED_CARRIER_NETWORK_OFFLOAD_MAP: 140 if (value instanceof Map) { 141 mDataSource.fromUnmergedCarrierNetworkOffloadMapDeserialized( 142 stringMapToIntegerMap((Map<String, Boolean>) value)); 143 } 144 break; 145 default: 146 Log.w(TAG, "Unknown tag under " 147 + XML_TAG_SECTION_HEADER 148 + ": " + valueName[0]); 149 break; 150 } 151 } 152 } 153 integerMapToStringMap(Map<Integer, Boolean> input)154 private Map<String, Boolean> integerMapToStringMap(Map<Integer, Boolean> input) { 155 Map<String, Boolean> output = new HashMap<>(); 156 if (input == null) { 157 return output; 158 } 159 for (Map.Entry<Integer, Boolean> entry : input.entrySet()) { 160 output.put(Integer.toString(entry.getKey()), entry.getValue()); 161 } 162 return output; 163 } 164 stringMapToIntegerMap(Map<String, Boolean> input)165 private Map<Integer, Boolean> stringMapToIntegerMap(Map<String, Boolean> input) { 166 Map<Integer, Boolean> output = new HashMap<>(); 167 if (input == null) { 168 return output; 169 } 170 for (Map.Entry<String, Boolean> entry : input.entrySet()) { 171 try { 172 output.put(Integer.valueOf(entry.getKey()), entry.getValue()); 173 } catch (NumberFormatException e) { 174 Log.e(TAG, "Failed to Integer convert: " + entry.getKey()); 175 } 176 } 177 return output; 178 } 179 180 @Override resetData()181 public void resetData() { 182 mDataSource.reset(); 183 } 184 185 @Override hasNewDataToSerialize()186 public boolean hasNewDataToSerialize() { 187 return mDataSource.hasNewDataToSerialize(); 188 } 189 190 @Override getName()191 public String getName() { 192 return XML_TAG_SECTION_HEADER; 193 } 194 195 @Override getStoreFileId()196 public int getStoreFileId() { 197 // User general store. 198 return WifiConfigStore.STORE_FILE_SHARED_GENERAL; 199 } 200 } 201