• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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.Nullable;
20 import android.net.wifi.SecurityParams;
21 import android.util.ArraySet;
22 import android.util.Log;
23 
24 import com.android.server.wifi.WifiConfigStore.StoreData;
25 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
26 import com.android.server.wifi.util.XmlUtil;
27 
28 import org.xmlpull.v1.XmlPullParser;
29 import org.xmlpull.v1.XmlPullParserException;
30 import org.xmlpull.v1.XmlSerializer;
31 
32 import java.io.IOException;
33 import java.util.Collections;
34 import java.util.Set;
35 
36 /**
37  * Config store data for Wifi Wake.
38  */
39 public class WakeupConfigStoreData implements StoreData {
40     private static final String TAG = "WakeupConfigStoreData";
41 
42     private static final String XML_TAG_FEATURE_STATE_SECTION = "FeatureState";
43     private static final String XML_TAG_IS_ACTIVE = "IsActive";
44     private static final String XML_TAG_IS_ONBOARDED = "IsOnboarded";
45     private static final String XML_TAG_NOTIFICATIONS_SHOWN = "NotificationsShown";
46     private static final String XML_TAG_NETWORK_SECTION = "Network";
47     private static final String XML_TAG_SSID = "SSID";
48     private static final String XML_TAG_SECURITY = "Security";
49     private static final String XML_TAG_SECURITY_PARAMS_LIST = "SecurityParamsList";
50     private static final String XML_TAG_SECURITY_PARAMS = "SecurityParams";
51     private static final String XML_TAG_SECURITY_TYPE = "SecurityType";
52     private static final String XML_TAG_SAE_IS_H2E_ONLY_MODE = "SaeIsH2eOnlyMode";
53     private static final String XML_TAG_SAE_IS_PK_ONLY_MODE = "SaeIsPkOnlyMode";
54     private static final String XML_TAG_IS_ADDED_BY_AUTO_UPGRADE = "IsAddedByAutoUpgrade";
55 
56     private final DataSource<Boolean> mIsActiveDataSource;
57     private final DataSource<Boolean> mIsOnboardedDataSource;
58     private final DataSource<Integer> mNotificationsDataSource;
59     private final DataSource<Set<ScanResultMatchInfo>> mNetworkDataSource;
60     private boolean mHasBeenRead = false;
61 
62     /**
63      * Interface defining a data source for the store data.
64      *
65      * @param <T> Type of data source
66      */
67     public interface DataSource<T> {
68         /**
69          * Returns the data from the data source.
70          */
getData()71         T getData();
72 
73         /**
74          * Updates the data in the data source.
75          *
76          * @param data Data retrieved from the store
77          */
setData(T data)78         void setData(T data);
79     }
80 
81     /**
82      * Creates the config store data with its data sources.
83      *
84      * @param isActiveDataSource Data source for isActive
85      * @param networkDataSource Data source for the locked network list
86      */
WakeupConfigStoreData( DataSource<Boolean> isActiveDataSource, DataSource<Boolean> isOnboardedDataSource, DataSource<Integer> notificationsDataSource, DataSource<Set<ScanResultMatchInfo>> networkDataSource)87     public WakeupConfigStoreData(
88             DataSource<Boolean> isActiveDataSource,
89             DataSource<Boolean> isOnboardedDataSource,
90             DataSource<Integer> notificationsDataSource,
91             DataSource<Set<ScanResultMatchInfo>> networkDataSource) {
92         mIsActiveDataSource = isActiveDataSource;
93         mIsOnboardedDataSource = isOnboardedDataSource;
94         mNotificationsDataSource = notificationsDataSource;
95         mNetworkDataSource = networkDataSource;
96     }
97 
98     /**
99      * Returns whether the user store has been read.
100      */
hasBeenRead()101     public boolean hasBeenRead() {
102         return mHasBeenRead;
103     }
104 
105     @Override
serializeData(XmlSerializer out, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)106     public void serializeData(XmlSerializer out,
107             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
108             throws XmlPullParserException, IOException {
109         writeFeatureState(out);
110 
111         for (ScanResultMatchInfo scanResultMatchInfo : mNetworkDataSource.getData()) {
112             writeNetwork(out, scanResultMatchInfo);
113         }
114     }
115 
116     /**
117      * Writes the current state of Wifi Wake to an XML output stream.
118      *
119      * @param out XML output stream
120      * @throws XmlPullParserException
121      * @throws IOException
122      */
writeFeatureState(XmlSerializer out)123     private void writeFeatureState(XmlSerializer out)
124             throws IOException, XmlPullParserException {
125         XmlUtil.writeNextSectionStart(out, XML_TAG_FEATURE_STATE_SECTION);
126 
127         XmlUtil.writeNextValue(out, XML_TAG_IS_ACTIVE, mIsActiveDataSource.getData());
128         XmlUtil.writeNextValue(out, XML_TAG_IS_ONBOARDED, mIsOnboardedDataSource.getData());
129         XmlUtil.writeNextValue(out, XML_TAG_NOTIFICATIONS_SHOWN,
130                 mNotificationsDataSource.getData());
131 
132         XmlUtil.writeNextSectionEnd(out, XML_TAG_FEATURE_STATE_SECTION);
133     }
134 
writeSecurityParamsList( XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo)135     private void writeSecurityParamsList(
136             XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo)
137             throws XmlPullParserException, IOException {
138         XmlUtil.writeNextSectionStart(out, XML_TAG_SECURITY_PARAMS_LIST);
139         for (SecurityParams params: scanResultMatchInfo.securityParamsList) {
140             XmlUtil.writeNextSectionStart(out, XML_TAG_SECURITY_PARAMS);
141             XmlUtil.writeNextValue(
142                     out, XML_TAG_SECURITY_TYPE,
143                     params.getSecurityType());
144             XmlUtil.writeNextValue(
145                     out, XML_TAG_SAE_IS_H2E_ONLY_MODE,
146                     params.isSaeH2eOnlyMode());
147             XmlUtil.writeNextValue(
148                     out, XML_TAG_SAE_IS_PK_ONLY_MODE,
149                     params.isSaePkOnlyMode());
150             XmlUtil.writeNextValue(
151                     out, XML_TAG_IS_ADDED_BY_AUTO_UPGRADE,
152                     params.isAddedByAutoUpgrade());
153             XmlUtil.writeNextSectionEnd(out, XML_TAG_SECURITY_PARAMS);
154         }
155         XmlUtil.writeNextSectionEnd(out, XML_TAG_SECURITY_PARAMS_LIST);
156     }
157 
158     /**
159      * Writes a {@link ScanResultMatchInfo} to an XML output stream.
160      *
161      * @param out XML output stream
162      * @param scanResultMatchInfo The ScanResultMatchInfo to serialize
163      * @throws XmlPullParserException
164      * @throws IOException
165      */
writeNetwork(XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo)166     private void writeNetwork(XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo)
167             throws XmlPullParserException, IOException {
168         XmlUtil.writeNextSectionStart(out, XML_TAG_NETWORK_SECTION);
169 
170         XmlUtil.writeNextValue(out, XML_TAG_SSID, scanResultMatchInfo.networkSsid);
171         writeSecurityParamsList(out, scanResultMatchInfo);
172 
173         XmlUtil.writeNextSectionEnd(out, XML_TAG_NETWORK_SECTION);
174     }
175 
176     @Override
deserializeData(XmlPullParser in, int outerTagDepth, @WifiConfigStore.Version int version, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)177     public void deserializeData(XmlPullParser in, int outerTagDepth,
178             @WifiConfigStore.Version int version,
179             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
180             throws XmlPullParserException, IOException {
181         if (!mHasBeenRead) {
182             Log.d(TAG, "WifiWake user data has been read");
183             mHasBeenRead = true;
184         }
185         // Ignore empty reads.
186         if (in == null) {
187             return;
188         }
189 
190         Set<ScanResultMatchInfo> networks = new ArraySet<>();
191 
192         String[] headerName = new String[1];
193         while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) {
194             switch (headerName[0]) {
195                 case XML_TAG_FEATURE_STATE_SECTION:
196                     parseFeatureState(in, outerTagDepth + 1);
197                     break;
198                 case XML_TAG_NETWORK_SECTION:
199                     networks.add(parseNetwork(in, outerTagDepth + 1));
200                     break;
201             }
202         }
203 
204         mNetworkDataSource.setData(networks);
205     }
206 
207     /**
208      * Parses the state of Wifi Wake from an XML input stream and sets the respective data sources.
209      *
210      * @param in XML input stream
211      * @param outerTagDepth XML tag depth of the containing section
212      * @throws IOException
213      * @throws XmlPullParserException
214      */
parseFeatureState(XmlPullParser in, int outerTagDepth)215     private void parseFeatureState(XmlPullParser in, int outerTagDepth)
216             throws IOException, XmlPullParserException {
217         boolean isActive = false;
218         boolean isOnboarded = false;
219         int notificationsShown = 0;
220 
221         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
222             String[] valueName = new String[1];
223             Object value = XmlUtil.readCurrentValue(in, valueName);
224             if (valueName[0] == null) {
225                 throw new XmlPullParserException("Missing value name");
226             }
227             switch (valueName[0]) {
228                 case XML_TAG_IS_ACTIVE:
229                     isActive = (Boolean) value;
230                     break;
231                 case XML_TAG_IS_ONBOARDED:
232                     isOnboarded = (Boolean) value;
233                     break;
234                 case XML_TAG_NOTIFICATIONS_SHOWN:
235                     notificationsShown = (Integer) value;
236                     break;
237                 default:
238                     Log.w(TAG, "Unknown value found: " + valueName[0]);
239                     break;
240             }
241         }
242 
243         mIsActiveDataSource.setData(isActive);
244         mIsOnboardedDataSource.setData(isOnboarded);
245         mNotificationsDataSource.setData(notificationsShown);
246     }
247 
parseSecurityParams(XmlPullParser in, int outerTagDepth)248     private SecurityParams parseSecurityParams(XmlPullParser in, int outerTagDepth)
249             throws IOException, XmlPullParserException {
250         SecurityParams params = null;
251         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
252             String[] valueName = new String[1];
253             Object value = XmlUtil.readCurrentValue(in, valueName);
254             String tagName = valueName[0];
255             if (tagName == null) {
256                 throw new XmlPullParserException("Missing value name");
257             }
258             switch (tagName) {
259                 case XML_TAG_SECURITY_TYPE:
260                     params = SecurityParams.createSecurityParamsBySecurityType((int) value);
261                     break;
262                 case XML_TAG_SAE_IS_H2E_ONLY_MODE:
263                     if (null == params) {
264                         throw new XmlPullParserException("Missing security type.");
265                     }
266                     params.enableSaeH2eOnlyMode((boolean) value);
267                     break;
268                 case XML_TAG_SAE_IS_PK_ONLY_MODE:
269                     if (null == params) {
270                         throw new XmlPullParserException("Missing security type.");
271                     }
272                     params.enableSaePkOnlyMode((boolean) value);
273                     break;
274                 case XML_TAG_IS_ADDED_BY_AUTO_UPGRADE:
275                     if (null == params) {
276                         throw new XmlPullParserException("Missing security type.");
277                     }
278                     params.setIsAddedByAutoUpgrade((boolean) value);
279                     break;
280             }
281         }
282         return params;
283     }
284 
parseSecurityParamsList( XmlPullParser in, int outerTagDepth, ScanResultMatchInfo scanResultMatchInfo)285     private void parseSecurityParamsList(
286             XmlPullParser in, int outerTagDepth, ScanResultMatchInfo scanResultMatchInfo)
287             throws IOException, XmlPullParserException {
288         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
289             switch (in.getName()) {
290                 case XML_TAG_SECURITY_PARAMS:
291                     SecurityParams params = parseSecurityParams(in, outerTagDepth + 1);
292                     if (null != params) {
293                         scanResultMatchInfo.securityParamsList.add(params);
294                     }
295                     break;
296             }
297         }
298 
299     }
300 
301     /**
302      * Parses a {@link ScanResultMatchInfo} from an XML input stream.
303      *
304      * @param in XML input stream
305      * @param outerTagDepth XML tag depth of the containing section
306      * @return The {@link ScanResultMatchInfo}
307      * @throws IOException
308      * @throws XmlPullParserException
309      */
parseNetwork(XmlPullParser in, int outerTagDepth)310     private ScanResultMatchInfo parseNetwork(XmlPullParser in, int outerTagDepth)
311             throws IOException, XmlPullParserException {
312         ScanResultMatchInfo scanResultMatchInfo = new ScanResultMatchInfo();
313         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
314             if (in.getAttributeValue(null, "name") == null) {
315                 String tagName = in.getName();
316                 if (tagName == null) {
317                     throw new XmlPullParserException("Unexpected null tag found");
318                 }
319                 switch (tagName) {
320                     case XML_TAG_SECURITY_PARAMS_LIST:
321                         parseSecurityParamsList(in, outerTagDepth + 1, scanResultMatchInfo);
322                         break;
323                 }
324                 continue;
325             }
326 
327             String[] valueName = new String[1];
328             Object value = XmlUtil.readCurrentValue(in, valueName);
329             if (valueName[0] == null) {
330                 throw new XmlPullParserException("Missing value name");
331             }
332             switch (valueName[0]) {
333                 case XML_TAG_SSID:
334                     scanResultMatchInfo.networkSsid = (String) value;
335                     break;
336                 case XML_TAG_SECURITY:
337                     // Migrate data from R to S.
338                     scanResultMatchInfo.securityParamsList.add(
339                             SecurityParams.createSecurityParamsBySecurityType((int) value));
340                     break;
341                 default:
342                     Log.w(TAG, "Ignoring unknown tag under " + TAG + ": " + valueName[0]);
343                     break;
344             }
345         }
346 
347         return scanResultMatchInfo;
348     }
349 
350     @Override
resetData()351     public void resetData() {
352         mNetworkDataSource.setData(Collections.emptySet());
353         mIsActiveDataSource.setData(false);
354         mIsOnboardedDataSource.setData(false);
355         mNotificationsDataSource.setData(0);
356     }
357 
358     @Override
hasNewDataToSerialize()359     public boolean hasNewDataToSerialize() {
360         // always persist.
361         return true;
362     }
363 
364     @Override
getName()365     public String getName() {
366         return TAG;
367     }
368 
369     @Override
getStoreFileId()370     public @WifiConfigStore.StoreFileId int getStoreFileId() {
371         // Shared general store.
372         return WifiConfigStore.STORE_FILE_USER_GENERAL;
373     }
374 }
375