auto import from //depot/cupcake/@135843
diff --git a/simulator/app/Preferences.cpp b/simulator/app/Preferences.cpp
new file mode 100644
index 0000000..039f1ff
--- /dev/null
+++ b/simulator/app/Preferences.cpp
@@ -0,0 +1,475 @@
+//
+// Copyright 2005 The Android Open Source Project
+//
+// Preferences file access.
+//
+
+// For compilers that support precompilation, include "wx/wx.h".
+#include "wx/wxprec.h"
+// Otherwise, include all standard headers
+#ifndef WX_PRECOMP
+//# include "wx/wx.h"
+# include "wx/string.h"
+#endif
+
+#include "Preferences.h"
+
+#include "utils.h"
+#include "tinyxml.h"
+
+static const char* kName = "name";
+static const char* kValue = "value";
+
+
+/*
+ * Load from a file.
+ */
+bool Preferences::Load(const char* fileName)
+{
+ assert(fileName != NULL);
+ printf("SimPref: reading preferences file '%s'\n", fileName);
+
+ // throw out any existing stuff
+ delete mpDoc;
+
+ mpDoc = new TiXmlDocument;
+ if (mpDoc == NULL)
+ return false;
+
+ if (!mpDoc->LoadFile(fileName)) {
+ fprintf(stderr, "SimPref: ERROR: failed loading '%s'\n", fileName);
+ if (mpDoc->ErrorRow() != 0)
+ fprintf(stderr, " XML: %s (row=%d col=%d)\n",
+ mpDoc->ErrorDesc(), mpDoc->ErrorRow(), mpDoc->ErrorCol());
+ else
+ fprintf(stderr, " XML: %s\n", mpDoc->ErrorDesc());
+ goto fail;
+ }
+
+ TiXmlNode* pPrefs;
+ pPrefs = mpDoc->FirstChild("prefs");
+ if (pPrefs == NULL) {
+ fprintf(stderr, "SimPref: ERROR: could not find <prefs> in '%s'\n",
+ fileName);
+ goto fail;
+ }
+
+ // set defaults for anything we haven't set explicitly
+ SetDefaults();
+
+ return true;
+
+fail:
+ delete mpDoc;
+ mpDoc = NULL;
+ return false;
+}
+
+/*
+ * Save to a file.
+ */
+bool Preferences::Save(const char* fileName)
+{
+ assert(fileName != NULL);
+
+ if (mpDoc == NULL)
+ return false;
+
+ if (!mpDoc->SaveFile(fileName)) {
+ fprintf(stderr, "SimPref: ERROR: failed saving '%s': %s\n",
+ fileName, mpDoc->ErrorDesc());
+ return false;
+ }
+
+ mDirty = false;
+
+ return true;
+}
+
+/*
+ * Create an empty collection of preferences.
+ */
+bool Preferences::Create(void)
+{
+ static const char* docBase =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
+ "<!-- Android device simulator preferences -->\n"
+ "<!-- This file is updated by the simulator -->\n"
+ "<prefs>\n"
+ "</prefs>\n";
+
+ // throw out any existing stuff
+ delete mpDoc;
+
+ // alloc and initialize
+ mpDoc = new TiXmlDocument;
+ if (mpDoc == NULL)
+ return false;
+
+ if (!mpDoc->Parse(docBase)) {
+ fprintf(stderr, "SimPref: bad docBase: %s\n", mpDoc->ErrorDesc());
+ return false;
+ }
+
+ SetDefaults();
+ mDirty = true; // should already be, mbut make sure
+ return true;
+}
+
+/*
+ * Add default values to XML doc.
+ *
+ * This isn't strictly necessary, because the functions that are interested
+ * in the preferences can set appropriate defaults themselves when the
+ * "get" function returns "false". However, in some cases a preference
+ * can be interesting to more than one function, and you either have to
+ * cut & paste the default value or write a "get default for xxx" function.
+ *
+ * We want this to work even if they already have an older config file, so
+ * this only sets values that don't already exist.
+ */
+void Preferences::SetDefaults(void)
+{
+ /* table of default values */
+ static const struct {
+ const char* type;
+ const char* name;
+ const char* value;
+ } kDefault[] = {
+ { "pref", "auto-power-on", "true" },
+ { "pref", "debug", "false" },
+ { "pref", "valgrind", "false" },
+ { "pref", "check-jni", "true" },
+ { "pref", "enable-sound", "true" },
+ { "pref", "enable-fake-camera", "true" },
+ { "pref", "java-vm", "Dalvik" },
+ /* goobuntu dapper needed LD_ASSUME_KERNEL or gdb choked badly */
+ { "pref", "ld-assume-kernel", "" /*2.4.19*/ },
+ { "pref", "launch-command",
+ "xterm -geom 80x60+10+10 -sb -title Simulator -e" },
+ { "pref", "launch-wrapper-args", "-wait" },
+ };
+ TiXmlNode* pPrefs;
+
+ assert(mpDoc != NULL);
+
+ pPrefs = mpDoc->FirstChild("prefs");
+
+ /*
+ * Look up the name. If it doesn't exist, add it.
+ */
+ for (int i = 0; i < NELEM(kDefault); i++) {
+ TiXmlNode* pNode = _FindNode(kDefault[i].type, kDefault[i].name);
+
+ if (pNode == NULL) {
+ TiXmlElement elem(kDefault[i].type);
+ elem.SetAttribute(kName, kDefault[i].name);
+ elem.SetAttribute(kValue, kDefault[i].value);
+ pPrefs->InsertEndChild(elem);
+
+ printf("SimPref: added default <%s> '%s'='%s'\n",
+ kDefault[i].type, kDefault[i].name, kDefault[i].value);
+ } else {
+ printf("SimPref: found existing <%s> '%s'\n",
+ kDefault[i].type, kDefault[i].name);
+ }
+ }
+}
+
+static TiXmlNode* get_next_node(TiXmlNode* pNode)
+{
+ if (!pNode->NoChildren())
+ {
+ pNode = pNode->FirstChild();
+ }
+ else if (pNode->NoChildren() &&
+ (pNode->NextSibling() == NULL))
+ {
+ pNode = pNode->Parent()->NextSibling();
+ }
+ else
+ {
+ pNode = pNode->NextSibling();
+ }
+ return pNode;
+}
+
+/*
+ * Returns the node with element type and name specified
+ *
+ * WARNING: this searches through the tree and returns the first matching
+ * node.
+ */
+TiXmlNode* Preferences::_FindNode(const char* type, const char* str) const
+{
+ assert((type != NULL) && (str != NULL));
+ TiXmlNode* pRoot;
+ TiXmlNode* pNode;
+
+ pRoot = mpDoc->FirstChild("prefs");
+ assert(pRoot != NULL);
+
+ for (pNode = pRoot->FirstChild(); pNode != NULL;)
+ {
+ if (pNode->Type() != TiXmlNode::ELEMENT ||
+ strcasecmp(pNode->Value(), type) != 0)
+ {
+ pNode = get_next_node(pNode);
+ continue;
+ }
+
+ TiXmlElement* pElem = pNode->ToElement();
+ assert(pElem != NULL);
+
+ const char* name = pElem->Attribute(kName);
+
+ /* 1. If the name is blank, something is wrong with the config file
+ * 2. If the name matches the passed in string, we found the node
+ * 3. If the node has children, descend another level
+ * 4. If there are no children and no siblings of the node, go up a level
+ * 5. Otherwise, grab the next sibling
+ */
+ if (name == NULL)
+ {
+ fprintf(stderr, "WARNING: found <%s> without name\n", type);
+ continue;
+ }
+ else if (strcasecmp(name, str) == 0)
+ {
+ return pNode;
+ }
+ else
+ {
+ pNode = get_next_node(pNode);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Locate the specified preference.
+ */
+TiXmlNode* Preferences::FindPref(const char* str) const
+{
+ TiXmlNode* pNode = _FindNode("pref", str);
+ return pNode;
+}
+
+/*
+ * Like FindPref(), but returns a TiXmlElement.
+ */
+TiXmlElement* Preferences::FindPrefElement(const char* str) const
+{
+ TiXmlNode* pNode;
+
+ pNode = FindPref(str);
+ if (pNode != NULL)
+ return pNode->ToElement();
+ return NULL;
+}
+
+/*
+ * Add a new preference entry with a blank entry for value. Returns a
+ * pointer to the new element.
+ */
+TiXmlElement* Preferences::AddPref(const char* str)
+{
+ assert(FindPref(str) == NULL);
+
+ TiXmlNode* pPrefs;
+
+ pPrefs = mpDoc->FirstChild("prefs");
+ assert(pPrefs != NULL);
+
+ TiXmlElement elem("pref");
+ elem.SetAttribute(kName, str);
+ elem.SetAttribute(kValue, "");
+ pPrefs->InsertEndChild(elem);
+
+ TiXmlNode* pNewPref = FindPref(str);
+ return pNewPref->ToElement();
+}
+
+/*
+ * Remove a node from the tree
+ */
+bool Preferences::_RemoveNode(TiXmlNode* pNode)
+{
+ if (pNode == NULL)
+ return false;
+
+ TiXmlNode* pParent = pNode->Parent();
+ if (pParent == NULL)
+ return false;
+
+ pParent->RemoveChild(pNode);
+ mDirty = true;
+ return true;
+}
+
+/*
+ * Remove a preference entry.
+ */
+bool Preferences::RemovePref(const char* delName)
+{
+ return _RemoveNode(FindPref(delName));
+}
+
+/*
+ * Test for existence.
+ */
+bool Preferences::Exists(const char* name) const
+{
+ TiXmlElement* pElem = FindPrefElement(name);
+ return (pElem != NULL);
+}
+
+/*
+ * Internal implemenations for getting values
+ */
+bool Preferences::_GetBool(TiXmlElement* pElem, bool* pVal) const
+{
+ if (pElem != NULL)
+ {
+ const char* str = pElem->Attribute(kValue);
+ if (str != NULL)
+ {
+ if (strcasecmp(str, "true") == 0)
+ *pVal = true;
+ else if (strcasecmp(str, "false") == 0)
+ *pVal = false;
+ else
+ {
+ printf("SimPref: evaluating as bool name='%s' val='%s'\n",
+ pElem->Attribute(kName), str);
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Preferences::_GetInt(TiXmlElement* pElem, int* pInt) const
+{
+ int val;
+ if (pElem != NULL && pElem->Attribute(kValue, &val) != NULL) {
+ *pInt = val;
+ return true;
+ }
+ return false;
+}
+
+bool Preferences::_GetDouble(TiXmlElement* pElem, double* pDouble) const
+{
+ double val;
+ if (pElem != NULL && pElem->Attribute(kValue, &val) != NULL) {
+ *pDouble = val;
+ return true;
+ }
+ return false;
+}
+
+bool Preferences::_GetString(TiXmlElement* pElem, wxString& str) const
+{
+ const char* val;
+ if (pElem != NULL) {
+ val = pElem->Attribute(kValue);
+ if (val != NULL) {
+ str = wxString::FromAscii(val);
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Get a value. Do not disturb "*pVal" unless we have something to return.
+ */
+bool Preferences::GetBool(const char* name, bool* pVal) const
+{
+ return _GetBool(FindPrefElement(name), pVal);
+}
+
+bool Preferences::GetInt(const char* name, int* pInt) const
+{
+ return _GetInt(FindPrefElement(name), pInt);
+}
+
+bool Preferences::GetDouble(const char* name, double* pDouble) const
+{
+ return _GetDouble(FindPrefElement(name), pDouble);
+}
+
+bool Preferences::GetString(const char* name, char** pVal) const
+{
+ wxString str = wxString::FromAscii(*pVal);
+ if (_GetString(FindPrefElement(name), str))
+ {
+ *pVal = android::strdupNew(str.ToAscii());
+ return true;
+ }
+ return false;
+}
+
+bool Preferences::GetString(const char* name, wxString& str) const
+{
+ return _GetString(FindPrefElement(name), str);
+}
+
+/*
+ * Set a value. If the preference already exists, and the value hasn't
+ * changed, don't do anything. This avoids setting the "dirty" flag
+ * unnecessarily.
+ */
+void Preferences::SetBool(const char* name, bool val)
+{
+ bool oldVal;
+ if (GetBool(name, &oldVal) && val == oldVal)
+ return;
+
+ SetString(name, val ? "true" : "false");
+ mDirty = true;
+}
+
+void Preferences::SetInt(const char* name, int val)
+{
+ int oldVal;
+ if (GetInt(name, &oldVal) && val == oldVal)
+ return;
+
+ TiXmlElement* pElem = FindPrefElement(name);
+ if (pElem == NULL)
+ pElem = AddPref(name);
+ pElem->SetAttribute(kValue, val);
+ mDirty = true;
+}
+
+void Preferences::SetDouble(const char* name, double val)
+{
+ double oldVal;
+ if (GetDouble(name, &oldVal) && val == oldVal)
+ return;
+
+ TiXmlElement* pElem = FindPrefElement(name);
+ if (pElem == NULL)
+ pElem = AddPref(name);
+ pElem->SetDoubleAttribute(kValue, val);
+ mDirty = true;
+}
+
+void Preferences::SetString(const char* name, const char* val)
+{
+ wxString oldVal;
+ if (GetString(name, /*ref*/oldVal) && strcmp(oldVal.ToAscii(), val) == 0)
+ return;
+
+ TiXmlElement* pElem = FindPrefElement(name);
+ if (pElem == NULL)
+ pElem = AddPref(name);
+ pElem->SetAttribute(kValue, val);
+ mDirty = true;
+}
+
+