189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown/* 289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * Copyright (C) 2012 The Android Open Source Project 389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * 489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * you may not use this file except in compliance with the License. 689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * You may obtain a copy of the License at 789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * 889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * 1089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * Unless required by applicable law or agreed to in writing, software 1189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * See the License for the specific language governing permissions and 1489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * limitations under the License. 1589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown */ 1689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 1789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownpackage com.android.server.display; 1889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 1989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport com.android.internal.util.FastXmlSerializer; 2089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport com.android.internal.util.XmlUtils; 2189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 2289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport org.xmlpull.v1.XmlPullParser; 2389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport org.xmlpull.v1.XmlPullParserException; 2489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport org.xmlpull.v1.XmlSerializer; 2589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 2689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.hardware.display.WifiDisplay; 2789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.util.AtomicFile; 2889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.util.Slog; 2989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.util.Xml; 3089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 3189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.BufferedInputStream; 3289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.BufferedOutputStream; 3389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.File; 3489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.FileNotFoundException; 3589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.FileOutputStream; 3689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.IOException; 3789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.io.InputStream; 3889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport java.util.ArrayList; 3989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 4089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport libcore.io.IoUtils; 4189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport libcore.util.Objects; 4289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 4389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown/** 4489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * Manages persistent state recorded by the display manager service as an XML file. 4589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * Caller must acquire lock on the data store before accessing it. 4689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * 4789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * File format: 4889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * <code> 4989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * <display-manager-state> 5089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * <remembered-wifi-displays> 5189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * <wifi-display deviceAddress="00:00:00:00:00:00" deviceName="XXXX" deviceAlias="YYYY" /> 5289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * >remembered-wifi-displays> 5389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * >/display-manager-state> 5489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * </code> 5589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * 5689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown * TODO: refactor this to extract common code shared with the input manager's data store 5789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown */ 5889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownfinal class PersistentDataStore { 5989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown static final String TAG = "DisplayManager"; 6089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 6189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // Remembered Wifi display devices. 6289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>(); 6389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 6489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // The atomic file used to safely read or write the file. 6589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private final AtomicFile mAtomicFile; 6689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 6789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // True if the data has been loaded. 6889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private boolean mLoaded; 6989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 7089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // True if there are changes to be saved. 7189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private boolean mDirty; 7289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 7389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public PersistentDataStore() { 7489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml")); 7589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 7689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 7789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void saveIfNeeded() { 7889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mDirty) { 7989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown save(); 8089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDirty = false; 8189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 8289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 8389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 8474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown public WifiDisplay getRememberedWifiDisplay(String deviceAddress) { 8574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown loadIfNeeded(); 8674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown int index = findRememberedWifiDisplay(deviceAddress); 8774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (index >= 0) { 8874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return mRememberedWifiDisplays.get(index); 8974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 9074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return null; 9174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 9274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 9389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public WifiDisplay[] getRememberedWifiDisplays() { 9489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown loadIfNeeded(); 9589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]); 9689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 9789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 9889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public WifiDisplay applyWifiDisplayAlias(WifiDisplay display) { 9989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (display != null) { 10089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown loadIfNeeded(); 10189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 102c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown String alias = null; 10389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown int index = findRememberedWifiDisplay(display.getDeviceAddress()); 10489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (index >= 0) { 105c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown alias = mRememberedWifiDisplays.get(index).getDeviceAlias(); 106c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 107c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (!Objects.equal(display.getDeviceAlias(), alias)) { 10821f603996ed83c7a9a6c430582e8a5af5ac13c6cChong Zhang return new WifiDisplay(display.getDeviceAddress(), display.getDeviceName(), 109ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang alias, display.isAvailable(), display.canConnect(), display.isRemembered()); 11089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 11189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 11289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return display; 11389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 11489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 11589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public WifiDisplay[] applyWifiDisplayAliases(WifiDisplay[] displays) { 11689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiDisplay[] results = displays; 11789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (results != null) { 11889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown int count = displays.length; 11989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (int i = 0; i < count; i++) { 12089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiDisplay result = applyWifiDisplayAlias(displays[i]); 12189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (result != displays[i]) { 12289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (results == displays) { 12389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown results = new WifiDisplay[count]; 12489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown System.arraycopy(displays, 0, results, 0, count); 12589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 12689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown results[i] = result; 12789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 12889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 12989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 13089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return results; 13189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 13289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 13389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public boolean rememberWifiDisplay(WifiDisplay display) { 13489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown loadIfNeeded(); 13589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 13689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown int index = findRememberedWifiDisplay(display.getDeviceAddress()); 13789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (index >= 0) { 13889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiDisplay other = mRememberedWifiDisplays.get(index); 13989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (other.equals(display)) { 14089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return false; // already remembered without change 14189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 14289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedWifiDisplays.set(index, display); 14389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } else { 14489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedWifiDisplays.add(display); 14589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 14689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown setDirty(); 14789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return true; 14889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 14989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 15089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public boolean forgetWifiDisplay(String deviceAddress) { 15189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown int index = findRememberedWifiDisplay(deviceAddress); 15289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (index >= 0) { 15389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedWifiDisplays.remove(index); 15489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown setDirty(); 15589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return true; 15689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 15789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return false; 15889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 15989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 16089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int findRememberedWifiDisplay(String deviceAddress) { 16189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown int count = mRememberedWifiDisplays.size(); 16289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (int i = 0; i < count; i++) { 16389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mRememberedWifiDisplays.get(i).getDeviceAddress().equals(deviceAddress)) { 16489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return i; 16589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 16689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 16789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return -1; 16889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 16989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 17089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void loadIfNeeded() { 17189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (!mLoaded) { 17289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown load(); 17389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mLoaded = true; 17489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 17789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void setDirty() { 17889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDirty = true; 17989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void clearState() { 18289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedWifiDisplays.clear(); 18389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void load() { 18689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown clearState(); 18789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final InputStream is; 18989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 19089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown is = mAtomicFile.openRead(); 19189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (FileNotFoundException ex) { 19289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return; 19389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 19589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown XmlPullParser parser; 19689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 19789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown parser = Xml.newPullParser(); 19889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown parser.setInput(new BufferedInputStream(is), null); 19989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown loadFromXml(parser); 20089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (IOException ex) { 20189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.w(TAG, "Failed to load display manager persistent store data.", ex); 20289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown clearState(); 20389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (XmlPullParserException ex) { 20489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.w(TAG, "Failed to load display manager persistent store data.", ex); 20589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown clearState(); 20689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } finally { 20789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown IoUtils.closeQuietly(is); 20889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 20989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 21089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 21189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void save() { 21289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final FileOutputStream os; 21389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 21489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown os = mAtomicFile.startWrite(); 21589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown boolean success = false; 21689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 21789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown XmlSerializer serializer = new FastXmlSerializer(); 21889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.setOutput(new BufferedOutputStream(os), "utf-8"); 21989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown saveToXml(serializer); 22089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.flush(); 22189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown success = true; 22289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } finally { 22389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (success) { 22489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAtomicFile.finishWrite(os); 22589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } else { 22689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAtomicFile.failWrite(os); 22789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 22889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 22989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (IOException ex) { 23089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.w(TAG, "Failed to save display manager persistent store data.", ex); 23189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 23289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 23389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 23489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void loadFromXml(XmlPullParser parser) 23589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throws IOException, XmlPullParserException { 23689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown XmlUtils.beginDocument(parser, "display-manager-state"); 23789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final int outerDepth = parser.getDepth(); 23889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown while (XmlUtils.nextElementWithin(parser, outerDepth)) { 23989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (parser.getName().equals("remembered-wifi-displays")) { 24089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown loadRememberedWifiDisplaysFromXml(parser); 24189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 24289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 24389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 24489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 24589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void loadRememberedWifiDisplaysFromXml(XmlPullParser parser) 24689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throws IOException, XmlPullParserException { 24789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final int outerDepth = parser.getDepth(); 24889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown while (XmlUtils.nextElementWithin(parser, outerDepth)) { 24989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (parser.getName().equals("wifi-display")) { 25089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String deviceAddress = parser.getAttributeValue(null, "deviceAddress"); 25189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String deviceName = parser.getAttributeValue(null, "deviceName"); 25289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String deviceAlias = parser.getAttributeValue(null, "deviceAlias"); 25389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (deviceAddress == null || deviceName == null) { 25489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throw new XmlPullParserException( 25589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown "Missing deviceAddress or deviceName attribute on wifi-display."); 25689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 25789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (findRememberedWifiDisplay(deviceAddress) >= 0) { 25889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throw new XmlPullParserException( 25989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown "Found duplicate wifi display device address."); 26089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 26289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedWifiDisplays.add( 263ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang new WifiDisplay(deviceAddress, deviceName, deviceAlias, 264ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang false, false, false)); 26589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 26989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void saveToXml(XmlSerializer serializer) throws IOException { 27089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.startDocument(null, true); 27189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 27289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.startTag(null, "display-manager-state"); 27389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.startTag(null, "remembered-wifi-displays"); 27489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (WifiDisplay display : mRememberedWifiDisplays) { 27589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.startTag(null, "wifi-display"); 27689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.attribute(null, "deviceAddress", display.getDeviceAddress()); 27789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.attribute(null, "deviceName", display.getDeviceName()); 27889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (display.getDeviceAlias() != null) { 27989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.attribute(null, "deviceAlias", display.getDeviceAlias()); 28089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.endTag(null, "wifi-display"); 28289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.endTag(null, "remembered-wifi-displays"); 28489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.endTag(null, "display-manager-state"); 28589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown serializer.endDocument(); 28689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown}