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