[1/2] OmniGears: add A2DP and wired headset event handling

Change-Id: Ia4a4fab9b6e6136f6e1437488a1d2c5faee897b3
diff --git a/res/drawable/ic_settings_event_service.xml b/res/drawable/ic_settings_event_service.xml
new file mode 100644
index 0000000..27a16e3
--- /dev/null
+++ b/res/drawable/ic_settings_event_service.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white" android:pathData="M2.2,16.06L3.88,12L2.2,7.94L6.26,6.26L7.94,2.2L12,3.88L16.06,2.2L17.74,6.26L21.8,7.94L20.12,12L21.8,16.06L17.74,17.74L16.06,21.8L12,20.12L7.94,21.8L6.26,17.74L2.2,16.06M13,17V15H11V17H13M13,13V7H11V13H13Z" />
+</vector>
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
index 87b7b23..88847ca 100644
--- a/res/values/custom_strings.xml
+++ b/res/values/custom_strings.xml
@@ -695,4 +695,12 @@
     <string name="not_ready_summary">Resolving...</string>
     <string name="resolve_failed_summary">Resolving app failed</string>
     <string name="disabled_entry">Disabled</string>
+
+    <string name="event_service_settings_title">Events</string>
+    <string name="category_media_player_title">Media player</string>
+    <string name="bt_a2dp_connect_app_title">Bluetooth A2DP connect</string>
+    <string name="headset_connect_app_title">Wired headset connect</string>
+    <string name="event_service_enabled_title">Enable event service</string>
+    <string name="event_service_running">Service is running</string>
+    <string name="event_service_stopped">Service is not running</string>
 </resources>
diff --git a/res/xml/event_service_settings.xml b/res/xml/event_service_settings.xml
new file mode 100644
index 0000000..7dbee8b
--- /dev/null
+++ b/res/xml/event_service_settings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2018 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/>.
+ -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:key="event_service_settings"
+    android:title="@string/event_service_settings_title">
+        <SwitchPreference
+            android:key="event_service_enabled"
+            android:title="@string/event_service_enabled_title"
+            android:persistent="false"/>
+
+        <PreferenceCategory
+            android:key="category_media_player"
+            android:title="@string/category_media_player_title">
+
+            <org.omnirom.omnigears.preference.AppSelectListPreference
+                android:key="bt_a2dp_connect_app"
+                android:title="@string/bt_a2dp_connect_app_title"
+                android:persistent="false"
+                android:dependency="event_service_enabled" />
+
+            <org.omnirom.omnigears.preference.AppSelectListPreference
+                android:key="headset_connect_app"
+                android:title="@string/headset_connect_app_title"
+                android:persistent="false"
+                android:dependency="event_service_enabled" />
+
+        </PreferenceCategory>
+</PreferenceScreen>
diff --git a/res/xml/omni_dashboard_fragment.xml b/res/xml/omni_dashboard_fragment.xml
index 4694ff7..88c5205 100644
--- a/res/xml/omni_dashboard_fragment.xml
+++ b/res/xml/omni_dashboard_fragment.xml
@@ -57,6 +57,12 @@
         android:fragment="org.omnirom.omnigears.batterylight.BatteryLightSettings" />
 
     <Preference
+        android:key="event_service_settings"
+        android:title="@string/event_service_settings_title"
+        android:icon="@drawable/ic_settings_event_service"
+        android:fragment="org.omnirom.omnigears.service.EventServiceSettings" />
+
+    <Preference
         android:key="more_settings"
         android:title="@string/more_settings_title"
         android:icon="@drawable/ic_settings_more"
diff --git a/src/org/omnirom/omnigears/preference/AppSelectListPreference.java b/src/org/omnirom/omnigears/preference/AppSelectListPreference.java
index 8bb838b..b57a795 100644
--- a/src/org/omnirom/omnigears/preference/AppSelectListPreference.java
+++ b/src/org/omnirom/omnigears/preference/AppSelectListPreference.java
@@ -52,6 +52,7 @@
 public class AppSelectListPreference extends CustomDialogPreference {
 
     private static String TAG = "AppSelectListPreference";
+    public static final String DISABLED_ENTRY = "disabled";
 
     private AppSelectListAdapter mAdapter;
     private Drawable mAppIconDrawable;
diff --git a/src/org/omnirom/omnigears/service/BootCompletedReceiver.java b/src/org/omnirom/omnigears/service/BootCompletedReceiver.java
index cd55042..d5292e5 100644
--- a/src/org/omnirom/omnigears/service/BootCompletedReceiver.java
+++ b/src/org/omnirom/omnigears/service/BootCompletedReceiver.java
@@ -20,14 +20,22 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.util.Log;
 
 public class BootCompletedReceiver extends BroadcastReceiver {
     private static final String TAG = "OmniEventService";
     private static final boolean DEBUG = true;
+
+    private SharedPreferences getPrefs(Context context) {
+        return context.getSharedPreferences(EventServiceSettings.EVENTS_PREFERENCES_NAME, Context.MODE_PRIVATE);
+    }
+
     @Override
     public void onReceive(Context context, Intent intent) {
-        if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
-        context.startService(new Intent(context, EventService.class));
+        if (getPrefs(context).getBoolean(EventServiceSettings.EVENT_SERVICE_ENABLED, false)) {
+            if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
+            context.startService(new Intent(context, EventService.class));
+        }
     }
 }
diff --git a/src/org/omnirom/omnigears/service/EventService.java b/src/org/omnirom/omnigears/service/EventService.java
index 902e47b..79e4533 100644
--- a/src/org/omnirom/omnigears/service/EventService.java
+++ b/src/org/omnirom/omnigears/service/EventService.java
@@ -27,9 +27,11 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
@@ -38,6 +40,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.PowerManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -48,6 +51,7 @@
     private static final String TAG = "OmniEventService";
     private static final boolean DEBUG = true;
     private PowerManager.WakeLock mWakeLock;
+    private static boolean mIsRunning;
 
     private BroadcastReceiver mStateListener = new BroadcastReceiver() {
         @Override
@@ -70,6 +74,15 @@
                             BluetoothProfile.STATE_CONNECTED);
                     if (state == BluetoothProfile.STATE_CONNECTED) {
                         if (DEBUG) Log.d(TAG, "BluetoothProfile.STATE_CONNECTED = true" );
+                        String app = getPrefs(context).getString(EventServiceSettings.EVENT_A2DP_CONNECT, null);
+                        if (app != null) {
+                            if (DEBUG) Log.d(TAG, "AudioManager.ACTION_HEADSET_PLUG app = " + app);
+                            try {
+                                context.startActivityAsUser(createIntent(app), UserHandle.CURRENT);
+                            } catch (Exception e) {
+                                Log.e(TAG, "BluetoothProfile.STATE_CONNECTED", e);
+                            }
+                        }
                     } else {
                         if (DEBUG) Log.d(TAG, "BluetoothProfile.STATE_CONNECTED = false" );
                     }
@@ -78,6 +91,15 @@
                     boolean useHeadset = intent.getIntExtra("state", 0) == 1;
                     if (useHeadset) {
                         if (DEBUG) Log.d(TAG, "AudioManager.ACTION_HEADSET_PLUG = true" );
+                        String app = getPrefs(context).getString(EventServiceSettings.EVENT_WIRED_HEADSET_CONNECT, null);
+                        if (app != null) {
+                            if (DEBUG) Log.d(TAG, "AudioManager.ACTION_HEADSET_PLUG app = " + app);
+                            try {
+                                context.startActivityAsUser(createIntent(app), UserHandle.CURRENT);
+                            } catch (Exception e) {
+                                Log.e(TAG, "AudioManager.ACTION_HEADSET_PLUG", e);
+                            }
+                        }
                     } else {
                         if (DEBUG) Log.d(TAG, "AudioManager.ACTION_HEADSET_PLUG = false" );
                     }
@@ -103,7 +125,7 @@
         PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(true);
-
+        mIsRunning = true;
         registerListener();
     }
 
@@ -117,6 +139,7 @@
         super.onDestroy();
         if (DEBUG) Log.d(TAG, "onDestroy");
         unregisterListener();
+        mIsRunning = false;
     }
 
     private void registerListener() {
@@ -137,4 +160,22 @@
         } catch (Exception e) {
         }
     }
+
+    public static boolean isRunning() {
+        return mIsRunning;
+    }
+
+    private SharedPreferences getPrefs(Context context) {
+        return context.getSharedPreferences(EventServiceSettings.EVENTS_PREFERENCES_NAME, Context.MODE_PRIVATE);
+    }
+
+    private Intent createIntent(String value) {
+        ComponentName componentName = ComponentName.unflattenFromString(value);
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        intent.setComponent(componentName);
+        return intent;
+    }
 }
diff --git a/src/org/omnirom/omnigears/service/EventServiceSettings.java b/src/org/omnirom/omnigears/service/EventServiceSettings.java
new file mode 100644
index 0000000..e9ac4d3
--- /dev/null
+++ b/src/org/omnirom/omnigears/service/EventServiceSettings.java
@@ -0,0 +1,152 @@
+/*
+ *  Copyright (C) 2018 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.omnigears.service;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v14.preference.SwitchPreference;
+import android.provider.Settings;
+import android.provider.SearchIndexableResource;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+
+import org.omnirom.omnigears.preference.AppSelectListPreference;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class EventServiceSettings extends SettingsPreferenceFragment implements OnPreferenceChangeListener, Indexable {
+    private static final String TAG = "EventServiceSettings";
+    public static final String EVENTS_PREFERENCES_NAME = "event_service";
+
+    public static final String EVENT_A2DP_CONNECT = "bt_a2dp_connect_app";
+    public static final String EVENT_WIRED_HEADSET_CONNECT = "headset_connect_app";
+    public static final String EVENT_SERVICE_ENABLED = "event_service_enabled";
+
+    private AppSelectListPreference mA2DPappSelect;
+    private AppSelectListPreference mWiredHeadsetAppSelect;
+    private SwitchPreference mEnable;
+    private Handler mHandler = new Handler();
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.OMNI_SETTINGS;
+    }
+
+    private SharedPreferences getPrefs() {
+        return getActivity().getSharedPreferences(EVENTS_PREFERENCES_NAME, Context.MODE_PRIVATE);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.event_service_settings);
+
+        mEnable = (SwitchPreference) findPreference(EVENT_SERVICE_ENABLED);
+        mEnable.setChecked(getPrefs().getBoolean(EventServiceSettings.EVENT_SERVICE_ENABLED, false));
+        mEnable.setOnPreferenceChangeListener(this);
+        mEnable.setSummary(isServiceRunning() ? getResources().getString(R.string.event_service_running)
+                : getResources().getString(R.string.event_service_stopped));
+
+        mA2DPappSelect = (AppSelectListPreference) findPreference(EVENT_A2DP_CONNECT);
+        mEnable.setChecked(getPrefs().getBoolean(EventServiceSettings.EVENT_SERVICE_ENABLED, false));
+        String value = getPrefs().getString(EVENT_A2DP_CONNECT, null);
+        mA2DPappSelect.setValue(value);
+        mA2DPappSelect.setOnPreferenceChangeListener(this);
+
+        mWiredHeadsetAppSelect = (AppSelectListPreference) findPreference(EVENT_WIRED_HEADSET_CONNECT);
+        value = getPrefs().getString(EVENT_WIRED_HEADSET_CONNECT, null);
+        mWiredHeadsetAppSelect.setValue(value);
+        mWiredHeadsetAppSelect.setOnPreferenceChangeListener(this);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (preference == mA2DPappSelect) {
+            String value = (String) newValue;
+            boolean appDisabled = value.equals(AppSelectListPreference.DISABLED_ENTRY);
+            getPrefs().edit().putString(EVENT_A2DP_CONNECT, appDisabled ? null : value).commit();
+            return true;
+        } else if (preference == mWiredHeadsetAppSelect) {
+            String value = (String) newValue;
+            boolean appDisabled = value.equals(AppSelectListPreference.DISABLED_ENTRY);
+            getPrefs().edit().putString(EVENT_WIRED_HEADSET_CONNECT, appDisabled ? null : value).commit();
+            return true;
+        } else if (preference == mEnable) {
+            boolean value = ((Boolean) newValue).booleanValue();
+            if (value) {
+                getActivity().startService(new Intent(getActivity(), EventService.class));
+            } else {
+                getActivity().stopService(new Intent(getActivity(), EventService.class));
+            }
+            getPrefs().edit().putBoolean(EVENT_SERVICE_ENABLED, value).commit();
+            mHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mEnable.setSummary(isServiceRunning() ? getResources().getString(R.string.event_service_running)
+                            : getResources().getString(R.string.event_service_stopped));
+                }
+            }, 1000);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isServiceRunning() {
+        return EventService.isRunning();
+    }
+
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+                        boolean enabled) {
+                    ArrayList<SearchIndexableResource> result =
+                            new ArrayList<SearchIndexableResource>();
+
+                    SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.event_service_settings;
+                    result.add(sir);
+
+                    return result;
+                }
+
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    ArrayList<String> result = new ArrayList<String>();
+                    return result;
+                }
+    };
+}