• 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.util.ArraySet;
20 import android.util.Log;
21 
22 import com.android.server.wifi.WifiConfigStore.StoreData;
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.Collections;
31 import java.util.Set;
32 
33 /**
34  * Config store data for Wifi Wake.
35  */
36 public class WakeupConfigStoreData implements StoreData {
37     private static final String TAG = "WakeupConfigStoreData";
38 
39     private static final String XML_TAG_FEATURE_STATE_SECTION = "FeatureState";
40     private static final String XML_TAG_IS_ACTIVE = "IsActive";
41     private static final String XML_TAG_IS_ONBOARDED = "IsOnboarded";
42     private static final String XML_TAG_NOTIFICATIONS_SHOWN = "NotificationsShown";
43     private static final String XML_TAG_NETWORK_SECTION = "Network";
44     private static final String XML_TAG_SSID = "SSID";
45     private static final String XML_TAG_SECURITY = "Security";
46 
47     private final DataSource<Boolean> mIsActiveDataSource;
48     private final DataSource<Boolean> mIsOnboardedDataSource;
49     private final DataSource<Integer> mNotificationsDataSource;
50     private final DataSource<Set<ScanResultMatchInfo>> mNetworkDataSource;
51     private boolean mHasBeenRead = false;
52 
53     /**
54      * Interface defining a data source for the store data.
55      *
56      * @param <T> Type of data source
57      */
58     public interface DataSource<T> {
59         /**
60          * Returns the data from the data source.
61          */
getData()62         T getData();
63 
64         /**
65          * Updates the data in the data source.
66          *
67          * @param data Data retrieved from the store
68          */
setData(T data)69         void setData(T data);
70     }
71 
72     /**
73      * Creates the config store data with its data sources.
74      *
75      * @param isActiveDataSource Data source for isActive
76      * @param networkDataSource Data source for the locked network list
77      */
WakeupConfigStoreData( DataSource<Boolean> isActiveDataSource, DataSource<Boolean> isOnboardedDataSource, DataSource<Integer> notificationsDataSource, DataSource<Set<ScanResultMatchInfo>> networkDataSource)78     public WakeupConfigStoreData(
79             DataSource<Boolean> isActiveDataSource,
80             DataSource<Boolean> isOnboardedDataSource,
81             DataSource<Integer> notificationsDataSource,
82             DataSource<Set<ScanResultMatchInfo>> networkDataSource) {
83         mIsActiveDataSource = isActiveDataSource;
84         mIsOnboardedDataSource = isOnboardedDataSource;
85         mNotificationsDataSource = notificationsDataSource;
86         mNetworkDataSource = networkDataSource;
87     }
88 
89     /**
90      * Returns whether the user store has been read.
91      */
hasBeenRead()92     public boolean hasBeenRead() {
93         return mHasBeenRead;
94     }
95 
96     @Override
serializeData(XmlSerializer out)97     public void serializeData(XmlSerializer out)
98             throws XmlPullParserException, IOException {
99         writeFeatureState(out);
100 
101         for (ScanResultMatchInfo scanResultMatchInfo : mNetworkDataSource.getData()) {
102             writeNetwork(out, scanResultMatchInfo);
103         }
104     }
105 
106     /**
107      * Writes the current state of Wifi Wake to an XML output stream.
108      *
109      * @param out XML output stream
110      * @throws XmlPullParserException
111      * @throws IOException
112      */
writeFeatureState(XmlSerializer out)113     private void writeFeatureState(XmlSerializer out)
114             throws IOException, XmlPullParserException {
115         XmlUtil.writeNextSectionStart(out, XML_TAG_FEATURE_STATE_SECTION);
116 
117         XmlUtil.writeNextValue(out, XML_TAG_IS_ACTIVE, mIsActiveDataSource.getData());
118         XmlUtil.writeNextValue(out, XML_TAG_IS_ONBOARDED, mIsOnboardedDataSource.getData());
119         XmlUtil.writeNextValue(out, XML_TAG_NOTIFICATIONS_SHOWN,
120                 mNotificationsDataSource.getData());
121 
122         XmlUtil.writeNextSectionEnd(out, XML_TAG_FEATURE_STATE_SECTION);
123     }
124 
125     /**
126      * Writes a {@link ScanResultMatchInfo} to an XML output stream.
127      *
128      * @param out XML output stream
129      * @param scanResultMatchInfo The ScanResultMatchInfo to serialize
130      * @throws XmlPullParserException
131      * @throws IOException
132      */
writeNetwork(XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo)133     private void writeNetwork(XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo)
134             throws XmlPullParserException, IOException {
135         XmlUtil.writeNextSectionStart(out, XML_TAG_NETWORK_SECTION);
136 
137         XmlUtil.writeNextValue(out, XML_TAG_SSID, scanResultMatchInfo.networkSsid);
138         XmlUtil.writeNextValue(out, XML_TAG_SECURITY, scanResultMatchInfo.networkType);
139 
140         XmlUtil.writeNextSectionEnd(out, XML_TAG_NETWORK_SECTION);
141     }
142 
143     @Override
deserializeData(XmlPullParser in, int outerTagDepth)144     public void deserializeData(XmlPullParser in, int outerTagDepth)
145             throws XmlPullParserException, IOException {
146         if (!mHasBeenRead) {
147             Log.d(TAG, "WifiWake user data has been read");
148             mHasBeenRead = true;
149         }
150         // Ignore empty reads.
151         if (in == null) {
152             return;
153         }
154 
155         Set<ScanResultMatchInfo> networks = new ArraySet<>();
156 
157         String[] headerName = new String[1];
158         while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) {
159             switch (headerName[0]) {
160                 case XML_TAG_FEATURE_STATE_SECTION:
161                     parseFeatureState(in, outerTagDepth + 1);
162                     break;
163                 case XML_TAG_NETWORK_SECTION:
164                     networks.add(parseNetwork(in, outerTagDepth + 1));
165                     break;
166             }
167         }
168 
169         mNetworkDataSource.setData(networks);
170     }
171 
172     /**
173      * Parses the state of Wifi Wake from an XML input stream and sets the respective data sources.
174      *
175      * @param in XML input stream
176      * @param outerTagDepth XML tag depth of the containing section
177      * @throws IOException
178      * @throws XmlPullParserException
179      */
parseFeatureState(XmlPullParser in, int outerTagDepth)180     private void parseFeatureState(XmlPullParser in, int outerTagDepth)
181             throws IOException, XmlPullParserException {
182         boolean isActive = false;
183         boolean isOnboarded = false;
184         int notificationsShown = 0;
185 
186         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
187             String[] valueName = new String[1];
188             Object value = XmlUtil.readCurrentValue(in, valueName);
189             if (valueName[0] == null) {
190                 throw new XmlPullParserException("Missing value name");
191             }
192             switch (valueName[0]) {
193                 case XML_TAG_IS_ACTIVE:
194                     isActive = (Boolean) value;
195                     break;
196                 case XML_TAG_IS_ONBOARDED:
197                     isOnboarded = (Boolean) value;
198                     break;
199                 case XML_TAG_NOTIFICATIONS_SHOWN:
200                     notificationsShown = (Integer) value;
201                     break;
202                 default:
203                     throw new XmlPullParserException("Unknown value found: " + valueName[0]);
204             }
205         }
206 
207         mIsActiveDataSource.setData(isActive);
208         mIsOnboardedDataSource.setData(isOnboarded);
209         mNotificationsDataSource.setData(notificationsShown);
210     }
211 
212     /**
213      * Parses a {@link ScanResultMatchInfo} from an XML input stream.
214      *
215      * @param in XML input stream
216      * @param outerTagDepth XML tag depth of the containing section
217      * @return The {@link ScanResultMatchInfo}
218      * @throws IOException
219      * @throws XmlPullParserException
220      */
parseNetwork(XmlPullParser in, int outerTagDepth)221     private ScanResultMatchInfo parseNetwork(XmlPullParser in, int outerTagDepth)
222             throws IOException, XmlPullParserException {
223         ScanResultMatchInfo scanResultMatchInfo = new ScanResultMatchInfo();
224         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
225             String[] valueName = new String[1];
226             Object value = XmlUtil.readCurrentValue(in, valueName);
227             if (valueName[0] == null) {
228                 throw new XmlPullParserException("Missing value name");
229             }
230             switch (valueName[0]) {
231                 case XML_TAG_SSID:
232                     scanResultMatchInfo.networkSsid = (String) value;
233                     break;
234                 case XML_TAG_SECURITY:
235                     scanResultMatchInfo.networkType = (int) value;
236                     break;
237                 default:
238                     throw new XmlPullParserException("Unknown tag under " + TAG + ": "
239                             + valueName[0]);
240             }
241         }
242 
243         return scanResultMatchInfo;
244     }
245 
246     @Override
resetData()247     public void resetData() {
248         mNetworkDataSource.setData(Collections.emptySet());
249         mIsActiveDataSource.setData(false);
250         mIsOnboardedDataSource.setData(false);
251         mNotificationsDataSource.setData(0);
252     }
253 
254     @Override
hasNewDataToSerialize()255     public boolean hasNewDataToSerialize() {
256         // always persist.
257         return true;
258     }
259 
260     @Override
getName()261     public String getName() {
262         return TAG;
263     }
264 
265     @Override
getStoreFileId()266     public @WifiConfigStore.StoreFileId int getStoreFileId() {
267         // Shared general store.
268         return WifiConfigStore.STORE_FILE_USER_GENERAL;
269     }
270 }
271