[1/5] OmniLib: Moving events into OmniBrain

Change-Id: I7e5e313375204ae2ecefb4f50f968cd51dcea6bb
diff --git a/Android.mk b/Android.mk
index 869b941..19e7ab5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,16 +13,13 @@
 
 LOCAL_STATIC_JAVA_LIBRARY := legacy-android-test
 
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
 LOCAL_JAR_EXCLUDE_FILES := none
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+LOCAL_RESOURCE_DIR := \
+        $(LOCAL_PATH)/res
+
 include frameworks/base/packages/SettingsLib/common.mk
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# For the test package.
-include $(call all-makefiles-under, $(LOCAL_PATH))
-
diff --git a/res/layout/action_item.xml b/res/layout/action_item.xml
new file mode 100644
index 0000000..0336067
--- /dev/null
+++ b/res/layout/action_item.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2016 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="64dp"
+    android:paddingStart="6dp"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="horizontal" >
+
+    <TextView
+        android:id="@+id/action_title"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:focusable="false"
+        android:textAppearance="?android:attr/textAppearanceListItem"
+        android:textAlignment="viewStart" />
+
+    <CheckBox android:id="@android:id/checkbox"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dip"
+        android:layout_gravity="center_vertical"
+        android:clickable="false"
+        android:focusable="false" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preference_action_list.xml b/res/layout/preference_action_list.xml
new file mode 100644
index 0000000..0e149de
--- /dev/null
+++ b/res/layout/preference_action_list.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2016 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingStart="@dimen/alert_dialog_padding_material"
+    android:paddingEnd="@dimen/alert_dialog_padding_material">
+
+    <ListView
+        android:id="@+id/action_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:divider="@null" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preference_wifi_ap_list.xml b/res/layout/preference_wifi_ap_list.xml
new file mode 100644
index 0000000..af5a456
--- /dev/null
+++ b/res/layout/preference_wifi_ap_list.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2016 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingStart="@dimen/alert_dialog_padding_material"
+    android:paddingEnd="@dimen/alert_dialog_padding_material">
+
+    <ListView
+        android:id="@+id/wifi_ap_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:divider="@null" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/wifi_ap_item.xml b/res/layout/wifi_ap_item.xml
new file mode 100644
index 0000000..fb265a2
--- /dev/null
+++ b/res/layout/wifi_ap_item.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2016 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="64dp"
+    android:paddingStart="6dp"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="horizontal" >
+
+    <TextView
+        android:id="@+id/ap_name"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:focusable="false"
+        android:textAppearance="?android:attr/textAppearanceListItem"
+        android:textAlignment="viewStart" />
+
+    <CheckBox android:id="@android:id/checkbox"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dip"
+        android:layout_gravity="center_vertical"
+        android:clickable="false"
+        android:focusable="false" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 21628e8..ed5ebaf 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
+
 <!--  Copyright (C) 2013 The OmniROM Project
 
   Parts Copyright (C) 2012-2013 The CyanogenMod Project
@@ -18,7 +19,7 @@
  -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-<string-array name="entries_led_colors" translatable="false">
+    <string-array name="entries_led_colors" translatable="false">
         <item>@string/led_color_green</item>
         <item>@string/led_color_red</item>
     </string-array>
diff --git a/res/values/custom_attrs.xml b/res/values/custom_attrs.xml
index 658eed8..c7b38dc 100644
--- a/res/values/custom_attrs.xml
+++ b/res/values/custom_attrs.xml
@@ -31,4 +31,4 @@
         <attr name="multiColor" format="boolean" />
         <attr name="withAlpha" format="boolean" />
     </declare-styleable>
-</resources>
+</resources>
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..d31d2fe
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,22 @@
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <style name="preference_icon_frame">
+        <item name="android:layout_marginStart">-4dp</item>
+        <item name="android:minWidth">60dp</item>
+    </style>
+</resources>
diff --git a/src/org/omnirom/omnilib/actions/OmniAction.java b/src/org/omnirom/omnilib/actions/OmniAction.java
new file mode 100644
index 0000000..9c889a4
--- /dev/null
+++ b/src/org/omnirom/omnilib/actions/OmniAction.java
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (C) 2014 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.omnirom.omnilib.actions;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.provider.Settings;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class OmniAction {
+    private static final String TAG = "OmniAction";
+
+    public String key = null;
+    public String title = null;
+    public String broadcast = null;
+    public String value = null;
+    public String value_type = null;
+    public String value_key = null;
+    public String type = null;
+    public String setting = null;
+    public String setting_type = null;
+
+    private Context mContext;
+
+    public OmniAction(Context context, AttributeSet attrs) {
+        mContext = context;
+        parseAttrs(attrs);
+    }
+
+    private void parseAttrs(AttributeSet attrs) {
+        for (int i = 0; i < attrs.getAttributeCount(); i++) {
+            String attr = attrs.getAttributeName(i);
+            switch (attr) {
+                case "setting":
+                    setting = attrs.getAttributeValue(i);
+                    break;
+                case "setting_type":
+                    setting_type = attrs.getAttributeValue(i);
+                    break;
+                case "broadcast":
+                    broadcast = attrs.getAttributeValue(i);
+                    break;
+                case "key":
+                    key = attrs.getAttributeValue(i);
+                    break;
+                case "value":
+                    value = attrs.getAttributeValue(i);
+                    break;
+                case "value_type":
+                    value_type = attrs.getAttributeValue(i);
+                    break;
+                case "value_key":
+                    value_key = attrs.getAttributeValue(i);
+                    break;
+                case "title":
+                    title = mContext.getString(attrs.getAttributeResourceValue(i, 0));
+                    break;
+            }
+        }
+    }
+
+    public void execute() {
+        if (broadcast != null) {
+            executeBroadcast();
+            return;
+        }
+
+        if (setting != null && setting_type != null) {
+            executeSetting();
+            return;
+        }
+    }
+
+    private void executeBroadcast() {
+        if (broadcast != null) {
+            Intent i = new Intent(broadcast);
+
+            if (value != null) {
+                switch (value_type) {
+                    case "boolean":
+                        i.putExtra(value_key, Boolean.parseBoolean(value));
+                        break;
+                    default:
+                        i.putExtra(value_key, value);
+                }
+            }
+
+            mContext.sendBroadcastAsUser(i, UserHandle.CURRENT);
+        }
+    }
+
+    private void executeSetting() {
+        switch (setting_type) {
+            case "Secure":
+                switch (value_type) {
+                    case "int":
+                        Settings.Secure.putInt(mContext.getContentResolver(), setting, Integer.parseInt(value));
+                        break;
+                    default:
+                        Settings.Secure.putString(mContext.getContentResolver(), setting, value);
+                        break;
+                }
+                break;
+            case "Global":
+                switch (value_type) {
+                    case "int":
+                        Settings.Global.putInt(mContext.getContentResolver(), setting, Integer.parseInt(value));
+                        break;
+                    default:
+                        Settings.Global.putString(mContext.getContentResolver(), setting, value);
+                        break;
+                }
+                break;
+        }
+    }
+}
diff --git a/src/org/omnirom/omnilib/actions/OmniActionsInflate.java b/src/org/omnirom/omnilib/actions/OmniActionsInflate.java
new file mode 100644
index 0000000..8cc378f
--- /dev/null
+++ b/src/org/omnirom/omnilib/actions/OmniActionsInflate.java
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2014 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.omnirom.omnilib.actions;
+
+import android.content.Context;
+import android.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+
+public class OmniActionsInflate {
+    public static ArrayList<OmniAction> inflate(Context context, int xmlFileResId) throws Exception {
+        int token;
+        ArrayList<OmniAction> actions = new ArrayList<OmniAction>();
+        XmlResourceParser parser = context.getResources().getXml(xmlFileResId);
+
+        while ((token = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            if (token == XmlPullParser.START_TAG) {
+                if ("action".equals(parser.getName())) {
+                    actions.add(new OmniAction(context, parser));
+                }
+            }
+        }
+        return actions;
+    }
+}
diff --git a/src/org/omnirom/omnilib/fragments/OmniLibPreferenceFragment.java b/src/org/omnirom/omnilib/fragments/OmniLibPreferenceFragment.java
new file mode 100644
index 0000000..52a3aca
--- /dev/null
+++ b/src/org/omnirom/omnilib/fragments/OmniLibPreferenceFragment.java
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (C) 2016 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.omnirom.omnilib.fragments;
+
+import android.app.DialogFragment;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+
+import com.android.settingslib.CustomDialogPreference;
+
+import java.util.UUID;
+
+public abstract class OmniLibPreferenceFragment extends PreferenceFragment {
+
+    @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+        if (preference.getKey() == null) {
+            // Auto-key preferences that don't have a key, so the dialog can find them.
+            preference.setKey(UUID.randomUUID().toString());
+        }
+        DialogFragment f = null;
+        if (preference instanceof CustomDialogPreference) {
+            f = CustomDialogPreference.CustomPreferenceDialogFragment
+                    .newInstance(preference.getKey());
+        } else {
+            super.onDisplayPreferenceDialog(preference);
+            return;
+        }
+        f.setTargetFragment(this, 0);
+        f.show(getFragmentManager(), "dialog_preference");
+    }
+}
\ No newline at end of file
diff --git a/src/org/omnirom/omnilib/preference/OmniActionsListPreference.java b/src/org/omnirom/omnilib/preference/OmniActionsListPreference.java
new file mode 100644
index 0000000..8b7bb4e
--- /dev/null
+++ b/src/org/omnirom/omnilib/preference/OmniActionsListPreference.java
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (C) 2016 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.omnirom.omnilib.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import org.omnirom.omnilib.actions.OmniAction;
+import org.omnirom.omnilib.actions.OmniActionsInflate;
+
+import org.omnirom.omnilib.R;
+import com.android.settingslib.CustomDialogPreference;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class OmniActionsListPreference extends CustomDialogPreference {
+    private static final String TAG = "OmniActionsList";
+    private static final boolean DEBUG = true;
+
+    private ArrayList<OmniAction> oActionInfoList;
+    private ActionListAdapter mAdapter;
+    private List<String> mValues = new ArrayList<String>();
+    private Context mContext;
+
+    public OmniActionsListPreference(Context context) {
+        this(context, null);
+    }
+
+    public OmniActionsListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setDialogLayoutResource(R.layout.preference_action_list);
+        mContext = context;
+        setPositiveButtonText(R.string.action_save);
+        setNegativeButtonText(android.R.string.cancel);
+    }
+
+    public void setValues(Collection<String> values) {
+        mValues.clear();
+        mValues.addAll(values);
+    }
+
+    public Collection<String> getValues() {
+        return mValues;
+    }
+
+    public boolean loadActions(int xml_id) {
+        try {
+            oActionInfoList = OmniActionsInflate.inflate(mContext, xml_id);
+        } catch (Exception e) {
+            if (DEBUG) Log.e(TAG, "Load omni actions ", e);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+
+        mAdapter = new ActionListAdapter(getContext());
+        final ListView listView = (ListView) view.findViewById(R.id.action_list);
+        listView.setAdapter(mAdapter);
+        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                final AppViewHolder holder = (AppViewHolder) view.getTag();
+                final boolean isChecked = !holder.checkBox.isChecked();
+
+                holder.checkBox.setChecked(isChecked);
+                OmniAction info = mAdapter.getItem(position);
+
+                if (isChecked) {
+                    mValues.add(info.key);
+                } else {
+                    mValues.remove(info.key);
+                }
+            }
+        });
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+        if (positiveResult) {
+            callChangeListener(mValues.size() > 0 ? mValues : null);
+        }
+    }
+
+    public class ActionListAdapter extends ArrayAdapter<OmniAction> {
+        private final LayoutInflater mInflater;
+
+        public ActionListAdapter(Context context) {
+            super(context, 0);
+            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            addAll(oActionInfoList);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
+            convertView = holder.rootView;
+            OmniAction info = getItem(position);
+            holder.title.setText(info.title);
+            holder.checkBox.setChecked(mValues.contains(info.key));
+            return convertView;
+        }
+
+        @Override
+        public OmniAction getItem(int position) {
+            return oActionInfoList.get(position);
+        }
+    }
+
+    public static class AppViewHolder {
+        public View rootView;
+        public TextView title;
+        public CheckBox checkBox;
+
+        public static AppViewHolder createOrRecycle(LayoutInflater inflater, View convertView) {
+            if (convertView == null) {
+                convertView = inflater.inflate(R.layout.action_item, null);
+
+                // Creates a ViewHolder and store references to the two children views
+                // we want to bind data to.
+                AppViewHolder holder = new AppViewHolder();
+                holder.rootView = convertView;
+                holder.title = (TextView) convertView.findViewById(R.id.action_title);
+                holder.checkBox = (CheckBox) convertView.findViewById(android.R.id.checkbox);
+                convertView.setTag(holder);
+                return holder;
+            } else {
+                // Get the ViewHolder back to get fast access to the TextView
+                // and the ImageView.
+                return (AppViewHolder) convertView.getTag();
+            }
+        }
+    }
+}
+
diff --git a/src/org/omnirom/omnilib/preference/WifiSelectListPreference.java b/src/org/omnirom/omnilib/preference/WifiSelectListPreference.java
new file mode 100644
index 0000000..46b3d36
--- /dev/null
+++ b/src/org/omnirom/omnilib/preference/WifiSelectListPreference.java
@@ -0,0 +1,172 @@
+/*
+ *  Copyright (C) 2016 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.omnirom.omnilib.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.net.wifi.WifiManager;
+import android.icu.text.Collator;
+
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiSavedConfigUtils;
+
+import org.omnirom.omnilib.R;
+import com.android.settingslib.CustomDialogPreference;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Comparator;
+import java.util.Collections;
+
+public class WifiSelectListPreference extends CustomDialogPreference {
+    private List<AccessPoint> mAPInfoList;
+    private ActionListAdapter mAdapter;
+    private List<String> mValues = new ArrayList<String>();
+    private WifiManager mWifiManager;
+    private static final Comparator<AccessPoint> SAVED_NETWORK_COMPARATOR =
+            new Comparator<AccessPoint>() {
+                final Collator mCollator = Collator.getInstance();
+
+                @Override
+                public int compare(AccessPoint ap1, AccessPoint ap2) {
+                    return mCollator.compare(
+                            nullToEmpty(ap1.getSsidStr()), nullToEmpty(ap2.getSsidStr()));
+                }
+
+                private String nullToEmpty(String string) {
+                    return (string == null) ? "" : string;
+                }
+            };
+
+    public WifiSelectListPreference(Context context) {
+        this(context, null);
+    }
+
+    public WifiSelectListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setDialogLayoutResource(R.layout.preference_wifi_ap_list);
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mAPInfoList = WifiSavedConfigUtils.getAllConfigs(context, mWifiManager);
+        Collections.sort(mAPInfoList, SAVED_NETWORK_COMPARATOR);
+
+        setPositiveButtonText(R.string.action_save);
+        setNegativeButtonText(android.R.string.cancel);
+    }
+
+    public void setValues(Collection<String> values) {
+        mValues.clear();
+        mValues.addAll(values);
+    }
+
+    public Collection<String> getValues() {
+        return mValues;
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+
+        mAdapter = new ActionListAdapter(getContext());
+        final ListView listView = (ListView) view.findViewById(R.id.wifi_ap_list);
+        listView.setAdapter(mAdapter);
+        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                final AppViewHolder holder = (AppViewHolder) view.getTag();
+                final boolean isChecked = !holder.checkBox.isChecked();
+
+                holder.checkBox.setChecked(isChecked);
+                AccessPoint info = mAdapter.getItem(position);
+
+                if (isChecked) {
+                    mValues.add(info.getSsidStr());
+                } else {
+                    mValues.remove(info.getSsidStr());
+                }
+            }
+        });
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+        if (positiveResult) {
+            callChangeListener(mValues.size() > 0 ? mValues : null);
+        }
+    }
+
+    public class ActionListAdapter extends ArrayAdapter<AccessPoint> {
+        private final LayoutInflater mInflater;
+
+        public ActionListAdapter(Context context) {
+            super(context, 0);
+            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            addAll(mAPInfoList);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
+            convertView = holder.rootView;
+            AccessPoint info = getItem(position);
+            holder.title.setText(info.getSsidStr());
+            holder.checkBox.setChecked(mValues.contains(info.getSsidStr()));
+            return convertView;
+        }
+
+        @Override
+        public AccessPoint getItem(int position) {
+            return mAPInfoList.get(position);
+        }
+    }
+
+    public static class AppViewHolder {
+        public View rootView;
+        public TextView title;
+        public CheckBox checkBox;
+
+        public static AppViewHolder createOrRecycle(LayoutInflater inflater, View convertView) {
+            if (convertView == null) {
+                convertView = inflater.inflate(R.layout.wifi_ap_item, null);
+
+                // Creates a ViewHolder and store references to the two children views
+                // we want to bind data to.
+                AppViewHolder holder = new AppViewHolder();
+                holder.rootView = convertView;
+                holder.title = (TextView) convertView.findViewById(R.id.ap_name);
+                holder.checkBox = (CheckBox) convertView.findViewById(android.R.id.checkbox);
+                convertView.setTag(holder);
+                return holder;
+            } else {
+                // Get the ViewHolder back to get fast access to the TextView
+                // and the ImageView.
+                return (AppViewHolder) convertView.getTag();
+            }
+        }
+    }
+}
+