diff options
25 files changed, 880 insertions, 0 deletions
diff --git a/configpanel/Android.mk b/configpanel/Android.mk new file mode 100644 index 0000000..5e2fdd0 --- /dev/null +++ b/configpanel/Android.mk @@ -0,0 +1,32 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := true +LOCAL_PACKAGE_NAME := ConfigPanel +LOCAL_PRIVATE_PLATFORM_APIS := true +LOCAL_REQUIRED_MODULES := ZukPocketMode + +LOCAL_USE_AAPT2 := true + +LOCAL_STATIC_ANDROID_LIBRARIES := \ + android-support-v4 \ + android-support-v7-appcompat \ + android-support-v7-preference \ + android-support-v7-recyclerview \ + android-support-v13 \ + android-support-v14-preference \ + +LOCAL_STATIC_JAVA_LIBRARIES := \ + org.lineageos.platform.internal + +LOCAL_RESOURCE_DIR := \ + $(LOCAL_PATH)/res \ + $(TOP)/packages/resources/devicesettings/res + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_PACKAGE) diff --git a/configpanel/AndroidManifest.xml b/configpanel/AndroidManifest.xml new file mode 100644 index 0000000..f62e7fc --- /dev/null +++ b/configpanel/AndroidManifest.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2016 The CyanogenMod Project + Copyright (C) 2017-2018 The LineageOS 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.lineageos.settings.device" + android:versionCode="6" + android:versionName="2.5" + android:sharedUserId="android.uid.system"> + + <protected-broadcast android:name="org.lineageos.settings.device.CUST_UPDATE" /> + + <uses-permission android:name="lineageos.permission.HARDWARE_ABSTRACTION_ACCESS" /> + + <uses-sdk + android:minSdkVersion="27" /> + + <application + android:icon="@mipmap/ic_launcher" + android:label="@string/device_settings_app_name" + android:theme="@style/Theme.Main" + android:defaultToDeviceProtectedStorage="true" + android:directBootAware="true"> + + <provider + android:name=".ConfigPanelSearchIndexablesProvider" + android:authorities="org.lineageos.settings.device" + android:multiprocess="false" + android:grantUriPermissions="true" + android:permission="android.permission.READ_SEARCH_INDEXABLES" + android:exported="true"> + <intent-filter> + <action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" /> + </intent-filter> + </provider> + + <activity + android:name=".ButtonSettingsActivity" + android:label="@string/button_panel_title"> + <intent-filter> + <action android:name="org.lineageos.settings.device.ADDITIONAL_BUTTONS_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + + <activity android:name=".KeyHandler" /> + + <receiver android:name=".Startup" > + <intent-filter> + <action android:name="lineageos.intent.action.INITIALIZE_LINEAGE_HARDWARE" /> + </intent-filter> + </receiver> + </application> + +</manifest> diff --git a/configpanel/proguard.flags b/configpanel/proguard.flags new file mode 100644 index 0000000..43b57d9 --- /dev/null +++ b/configpanel/proguard.flags @@ -0,0 +1,3 @@ +-keepclasseswithmembers class * { + public <init>(android.content.Context, android.util.AttributeSet); +} diff --git a/configpanel/res/drawable/ic_settings_additional_buttons.xml b/configpanel/res/drawable/ic_settings_additional_buttons.xml new file mode 100644 index 0000000..044fc23 --- /dev/null +++ b/configpanel/res/drawable/ic_settings_additional_buttons.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2016 The CyanogenMod 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="@android:color/white" + android:pathData="M17,1L7,1C5.9,1,5,1.9,5,3v2h2v4H5v12c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z +M11,21H7v-2h4V21z M17,21 h-4v-2h4V21z" /> +</vector> diff --git a/configpanel/res/mipmap-anydpi/ic_launcher.xml b/configpanel/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..d8649ba --- /dev/null +++ b/configpanel/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (c) 2018 The LineageOS 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. +--> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@mipmap/ic_background"/> + <foreground android:drawable="@mipmap/ic_foreground"/> +</adaptive-icon> + diff --git a/configpanel/res/mipmap-hdpi/ic_background.png b/configpanel/res/mipmap-hdpi/ic_background.png Binary files differnew file mode 100644 index 0000000..f01deeb --- /dev/null +++ b/configpanel/res/mipmap-hdpi/ic_background.png diff --git a/configpanel/res/mipmap-hdpi/ic_foreground.png b/configpanel/res/mipmap-hdpi/ic_foreground.png Binary files differnew file mode 100644 index 0000000..97158bc --- /dev/null +++ b/configpanel/res/mipmap-hdpi/ic_foreground.png diff --git a/configpanel/res/mipmap-mdpi/ic_background.png b/configpanel/res/mipmap-mdpi/ic_background.png Binary files differnew file mode 100644 index 0000000..58bcf52 --- /dev/null +++ b/configpanel/res/mipmap-mdpi/ic_background.png diff --git a/configpanel/res/mipmap-mdpi/ic_foreground.png b/configpanel/res/mipmap-mdpi/ic_foreground.png Binary files differnew file mode 100644 index 0000000..7b9bc07 --- /dev/null +++ b/configpanel/res/mipmap-mdpi/ic_foreground.png diff --git a/configpanel/res/mipmap-xhdpi/ic_background.png b/configpanel/res/mipmap-xhdpi/ic_background.png Binary files differnew file mode 100644 index 0000000..681a199 --- /dev/null +++ b/configpanel/res/mipmap-xhdpi/ic_background.png diff --git a/configpanel/res/mipmap-xhdpi/ic_foreground.png b/configpanel/res/mipmap-xhdpi/ic_foreground.png Binary files differnew file mode 100644 index 0000000..c079116 --- /dev/null +++ b/configpanel/res/mipmap-xhdpi/ic_foreground.png diff --git a/configpanel/res/mipmap-xxhdpi/ic_background.png b/configpanel/res/mipmap-xxhdpi/ic_background.png Binary files differnew file mode 100644 index 0000000..1e707e8 --- /dev/null +++ b/configpanel/res/mipmap-xxhdpi/ic_background.png diff --git a/configpanel/res/mipmap-xxhdpi/ic_foreground.png b/configpanel/res/mipmap-xxhdpi/ic_foreground.png Binary files differnew file mode 100644 index 0000000..ecc70af --- /dev/null +++ b/configpanel/res/mipmap-xxhdpi/ic_foreground.png diff --git a/configpanel/res/mipmap-xxxhdpi/ic_background.png b/configpanel/res/mipmap-xxxhdpi/ic_background.png Binary files differnew file mode 100644 index 0000000..b6e860b --- /dev/null +++ b/configpanel/res/mipmap-xxxhdpi/ic_background.png diff --git a/configpanel/res/mipmap-xxxhdpi/ic_foreground.png b/configpanel/res/mipmap-xxxhdpi/ic_foreground.png Binary files differnew file mode 100644 index 0000000..3133594 --- /dev/null +++ b/configpanel/res/mipmap-xxxhdpi/ic_foreground.png diff --git a/configpanel/res/values/styles.xml b/configpanel/res/values/styles.xml new file mode 100644 index 0000000..8dbdd4f --- /dev/null +++ b/configpanel/res/values/styles.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014-2016 The CyanogenMod Project + (C) 2017 The LineageOS 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <style name="Theme.Main" parent="@android:style/Theme.DeviceDefault.Settings"> + <item name="preferenceCategoryStyle">@style/Theme.Main.PreferenceCategoryStyle</item> + <item name="preferenceFragmentStyle">@style/Theme.Main.PreferenceFragmentStyle</item> + <item name="preferenceStyle">@style/Theme.Main.PreferenceStyle</item> + <item name="preferenceTheme">@style/Theme.Main.PreferenceTheme</item> + <item name="switchPreferenceStyle">@style/Theme.Main.SwitchPreferenceStyle</item> + </style> + + <style name="Theme.Main.PreferenceCategoryStyle" parent="@*android:style/Preference.DeviceDefault.Category"> + <item name="allowDividerAbove">true</item> + <item name="allowDividerBelow">true</item> + <item name="android:layout">@layout/preference_category_material_settings</item> + </style> + + <style name="Theme.Main.PreferenceFragmentStyle" parent="@*android:style/PreferenceFragment.Material"> + <item name="allowDividerAfterLastItem">false</item> + </style> + + <style name="Theme.Main.PreferenceStyle" parent="@*android:style/Preference.DeviceDefault"> + <item name="allowDividerAbove">false</item> + <item name="allowDividerBelow">true</item> + <item name="singleLineTitle">false</item> + <item name="android:layout">@layout/preference_material_settings</item> + </style> + + <style name="Theme.Main.PreferenceTheme"> + </style> + + <style name="Theme.Main.SwitchPreferenceStyle" parent="@style/Theme.Main.PreferenceStyle"> + <item name="widgetLayout">@*android:layout/preference_widget_switch</item> + </style> +</resources> diff --git a/configpanel/res/xml/button_panel.xml b/configpanel/res/xml/button_panel.xml new file mode 100644 index 0000000..43f4902 --- /dev/null +++ b/configpanel/res/xml/button_panel.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2016 The CyanogenMod Project + (C) 2017 The LineageOS 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. +--> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + + <SwitchPreference + android:key="button_swap" + android:title="@string/button_swap_title" + android:summary="@string/button_swap_summary" /> + + <PreferenceCategory + android:key="fp_key" + android:title="@string/fingerprint_title" > + + <SwitchPreference + android:key="fp_home" + android:title="@string/fingerprint_as_home_title" + android:summary="@string/fingerprint_as_home_summary" /> + + <SwitchPreference + android:key="fp_wakeup" + android:title="@string/fingerprint_wakeup_title" + android:summary="@string/fingerprint_wakeup_summary" /> + + <SwitchPreference + android:key="fp_pocketmode" + android:title="@string/fingerprint_pocketmode_title" + android:summary="@string/fingerprint_pocketmode_summary" + android:dependency="fp_wakeup" /> + + </PreferenceCategory> + +</PreferenceScreen> diff --git a/configpanel/src/org/lineageos/settings/device/ButtonSettingsActivity.java b/configpanel/src/org/lineageos/settings/device/ButtonSettingsActivity.java new file mode 100644 index 0000000..737dbd5 --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/ButtonSettingsActivity.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * (C) 2017 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class ButtonSettingsActivity extends PreferenceActivity { + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getFragmentManager().beginTransaction().replace(android.R.id.content, + new ButtonSettingsFragment()).commit(); + } +} diff --git a/configpanel/src/org/lineageos/settings/device/ButtonSettingsFragment.java b/configpanel/src/org/lineageos/settings/device/ButtonSettingsFragment.java new file mode 100644 index 0000000..b951641 --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/ButtonSettingsFragment.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * (C) 2017 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import android.app.ActionBar; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v14.preference.PreferenceFragment; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.Preference.OnPreferenceChangeListener; +import android.support.v7.preference.PreferenceCategory; +import android.support.v7.preference.PreferenceManager; +import android.text.TextUtils; +import android.view.MenuItem; + +import org.lineageos.internal.util.FileUtils; +import org.lineageos.internal.util.PackageManagerUtils; + +public class ButtonSettingsFragment extends PreferenceFragment + implements OnPreferenceChangeListener { + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.button_panel); + final ActionBar actionBar = getActivity().getActionBar(); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + @Override + public void onResume() { + super.onResume(); + updatePreferencesBasedOnDependencies(); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + + String node = Constants.sBooleanNodePreferenceMap.get(preference.getKey()); + if (!TextUtils.isEmpty(node) && FileUtils.isFileWritable(node)) { + Boolean value = (Boolean) newValue; + FileUtils.writeLine(node, value ? "1" : "0"); + if (Constants.FP_WAKEUP_KEY.equals(preference.getKey())) { + value &= prefs.getBoolean(Constants.FP_POCKETMODE_KEY, false); + Utils.broadcastCustIntent(getContext(), value); + } + return true; + } + node = Constants.sStringNodePreferenceMap.get(preference.getKey()); + if (!TextUtils.isEmpty(node) && FileUtils.isFileWritable(node)) { + FileUtils.writeLine(node, (String) newValue); + return true; + } + + if (Constants.FP_POCKETMODE_KEY.equals(preference.getKey())) { + Utils.broadcastCustIntent(getContext(), (Boolean) newValue); + return true; + } + + return false; + } + + @Override + public void addPreferencesFromResource(int preferencesResId) { + super.addPreferencesFromResource(preferencesResId); + // Initialize node preferences + for (String pref : Constants.sBooleanNodePreferenceMap.keySet()) { + SwitchPreference b = (SwitchPreference) findPreference(pref); + if (b == null) continue; + b.setOnPreferenceChangeListener(this); + String node = Constants.sBooleanNodePreferenceMap.get(pref); + if (FileUtils.isFileReadable(node)) { + String curNodeValue = FileUtils.readOneLine(node); + b.setChecked(curNodeValue.equals("1")); + } else { + b.setEnabled(false); + } + } + for (String pref : Constants.sStringNodePreferenceMap.keySet()) { + ListPreference l = (ListPreference) findPreference(pref); + if (l == null) continue; + l.setOnPreferenceChangeListener(this); + String node = Constants.sStringNodePreferenceMap.get(pref); + if (FileUtils.isFileReadable(node)) { + l.setValue(FileUtils.readOneLine(node)); + } else { + l.setEnabled(false); + } + } + + // Initialize other preferences whose keys are not associated with nodes + final PreferenceCategory fingerprintCategory = + (PreferenceCategory) getPreferenceScreen().findPreference(Constants.CATEGORY_FP); + + SwitchPreference b = (SwitchPreference) findPreference(Constants.FP_POCKETMODE_KEY); + if (!PackageManagerUtils.isAppInstalled(getContext(), "org.lineageos.pocketmode")) { + fingerprintCategory.removePreference(b); + } else { + b.setOnPreferenceChangeListener(this); + } + + // Hide fingerprint features if the device doesn't support them + if (!FileUtils.fileExists(Constants.FP_HOME_KEY_NODE) && + !FileUtils.fileExists(Constants.FP_WAKEUP_NODE)) { + getPreferenceScreen().removePreference(fingerprintCategory); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + getActivity().onBackPressed(); + return true; + } + return false; + } + + private void updatePreferencesBasedOnDependencies() { + for (String pref : Constants.sNodeDependencyMap.keySet()) { + SwitchPreference b = (SwitchPreference) findPreference(pref); + if (b == null) continue; + String dependencyNode = Constants.sNodeDependencyMap.get(pref)[0]; + if (FileUtils.isFileReadable(dependencyNode)) { + String dependencyNodeValue = FileUtils.readOneLine(dependencyNode); + boolean shouldSetEnabled = dependencyNodeValue.equals( + Constants.sNodeDependencyMap.get(pref)[1]); + Utils.updateDependentPreference(getContext(), b, pref, shouldSetEnabled); + } + } + } +} diff --git a/configpanel/src/org/lineageos/settings/device/ConfigPanelSearchIndexablesProvider.java b/configpanel/src/org/lineageos/settings/device/ConfigPanelSearchIndexablesProvider.java new file mode 100644 index 0000000..c234791 --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/ConfigPanelSearchIndexablesProvider.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * (C) 2017-2018 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import android.content.Context; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.provider.SearchIndexableResource; +import android.provider.SearchIndexablesProvider; + +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID; +import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS; +import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS; +import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS; + +import org.lineageos.internal.util.FileUtils; +import org.lineageos.internal.util.PackageManagerUtils; + +import java.util.ArrayList; +import java.util.List; + +public class ConfigPanelSearchIndexablesProvider extends SearchIndexablesProvider { + private static final String TAG = "ConfigPanelSearchIndexablesProvider"; + + public static final int SEARCH_IDX_BUTTON_PANEL = 0; + + private static SearchIndexableResource[] INDEXABLE_RES = new SearchIndexableResource[]{ + new SearchIndexableResource(1, R.xml.button_panel, + ButtonSettingsActivity.class.getName(), + R.drawable.ic_settings_additional_buttons), + }; + + @Override + public boolean onCreate() { + return true; + } + + @Override + public Cursor queryXmlResources(String[] projection) { + MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS); + if (Startup.hasButtonProcs() /* show button panel */) { + cursor.addRow(generateResourceRef(INDEXABLE_RES[SEARCH_IDX_BUTTON_PANEL])); + } + return cursor; + } + + private static Object[] generateResourceRef(SearchIndexableResource sir) { + final Object[] ref = new Object[INDEXABLES_XML_RES_COLUMNS.length]; + ref[COLUMN_INDEX_XML_RES_RANK] = sir.rank; + ref[COLUMN_INDEX_XML_RES_RESID] = sir.xmlResId; + ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = null; + ref[COLUMN_INDEX_XML_RES_ICON_RESID] = sir.iconResId; + ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = "com.android.settings.action.EXTRA_SETTINGS"; + ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = "org.lineageos.settings.device"; + ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = sir.className; + return ref; + } + + private List<String> getNonIndexableKeys(Context context) { + List<String> keys = new ArrayList<>(); + if (!PackageManagerUtils.isAppInstalled(context, "org.lineageos.pocketmode")) { + keys.add(Constants.FP_POCKETMODE_KEY); + } + if (!FileUtils.fileExists(Constants.FP_HOME_KEY_NODE) && + !FileUtils.fileExists(Constants.FP_WAKEUP_NODE)) { + keys.add(Constants.FP_HOME_KEY); + keys.add(Constants.FP_WAKEUP_KEY); + } + return keys; + } + + @Override + public Cursor queryRawData(String[] projection) { + MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS); + return cursor; + } + + @Override + public Cursor queryNonIndexableKeys(String[] projection) { + MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS); + final Context context = getContext(); + + List<String> nonIndexableKeys = getNonIndexableKeys(context); + for (String nik : nonIndexableKeys) { + final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length]; + ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik; + cursor.addRow(ref); + } + return cursor; + } +} diff --git a/configpanel/src/org/lineageos/settings/device/Constants.java b/configpanel/src/org/lineageos/settings/device/Constants.java new file mode 100644 index 0000000..b673946 --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/Constants.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * (C) 2017-2018 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import org.lineageos.internal.util.FileUtils; + +import java.util.HashMap; +import java.util.Map; + +public class Constants { + + // Category keys + public static final String CATEGORY_FP = "fp_key"; + + // Preference keys + public static final String BUTTON_SWAP_KEY = "button_swap"; + public static final String FP_HOME_KEY = "fp_home"; + public static final String FP_POCKETMODE_KEY = "fp_pocketmode"; + public static final String FP_WAKEUP_KEY = "fp_wakeup"; + + // Nodes + public static final String CYTTSP_BUTTON_SWAP_NODE = "/proc/buttons/reversed_keys_enable"; + public static final String FP_HOME_KEY_NODE = "/sys/devices/soc/soc:fpc_fpc1020/enable_key_events"; + public static final String FP_WAKEUP_NODE = "/sys/devices/soc/soc:fpc_fpc1020/enable_wakeup"; + public static final String TOUCHPANEL_BUTTON_SWAP_NODE = "/proc/touchpanel/reversed_keys_enable"; + public static final String VIRTUAL_KEYS_NODE = "/proc/touchpanel/capacitive_keys_enable"; + + // Intents + public static final String CUST_INTENT = "org.lineageos.settings.device.CUST_UPDATE"; + public static final String CUST_INTENT_EXTRA = "pocketmode_service"; + + // Holds <preference_key> -> <proc_node> mapping + public static final Map<String, String> sBooleanNodePreferenceMap = new HashMap<>(); + public static final Map<String, String> sStringNodePreferenceMap = new HashMap<>(); + + // Holds <preference_key> -> <default_values> mapping + public static final Map<String, Object> sNodeDefaultMap = new HashMap<>(); + + // Holds <preference_key> -> <user_set_values> mapping + public static final Map<String, Object[]> sNodeUserSetValuesMap = new HashMap<>(); + + // Holds <preference_key> -> <dependency_check> mapping + public static final Map<String, String[]> sNodeDependencyMap = new HashMap<>(); + + public static final String[] sButtonPrefKeys = { + BUTTON_SWAP_KEY, + FP_HOME_KEY, + FP_WAKEUP_KEY + }; + + static { + if (FileUtils.fileExists(Constants.CYTTSP_BUTTON_SWAP_NODE)) { + sBooleanNodePreferenceMap.put(BUTTON_SWAP_KEY, CYTTSP_BUTTON_SWAP_NODE); + } else if (FileUtils.fileExists(Constants.TOUCHPANEL_BUTTON_SWAP_NODE)) { + sBooleanNodePreferenceMap.put(BUTTON_SWAP_KEY, TOUCHPANEL_BUTTON_SWAP_NODE); + } + sBooleanNodePreferenceMap.put(FP_HOME_KEY, FP_HOME_KEY_NODE); + sBooleanNodePreferenceMap.put(FP_WAKEUP_KEY, FP_WAKEUP_NODE); + + sNodeDefaultMap.put(BUTTON_SWAP_KEY, false); + sNodeDefaultMap.put(FP_HOME_KEY, false); + sNodeDefaultMap.put(FP_WAKEUP_KEY, true); + + sNodeDependencyMap.put(FP_HOME_KEY, new String[]{ VIRTUAL_KEYS_NODE, "1" }); + } +} diff --git a/configpanel/src/org/lineageos/settings/device/KeyHandler.java b/configpanel/src/org/lineageos/settings/device/KeyHandler.java new file mode 100644 index 0000000..247624b --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/KeyHandler.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2017-2019 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Log; +import android.view.KeyEvent; + +import com.android.internal.os.DeviceKeyHandler; + +import lineageos.providers.LineageSettings; + +import org.lineageos.internal.util.FileUtils; + +public class KeyHandler implements DeviceKeyHandler { + + private static final String TAG = KeyHandler.class.getSimpleName(); + + private static final String FP_HOME_NODE = "/sys/devices/soc/soc:fpc_fpc1020/enable_key_events"; + + private static boolean sScreenTurnedOn = true; + private static final boolean DEBUG = false; + + private final Context mContext; + + private final BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { + sScreenTurnedOn = false; + } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { + sScreenTurnedOn = true; + } + } + }; + + public KeyHandler(Context context) { + mContext = context; + + IntentFilter screenStateFilter = new IntentFilter(); + screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF); + screenStateFilter.addAction(Intent.ACTION_SCREEN_ON); + mContext.registerReceiver(mScreenStateReceiver, screenStateFilter); + } + + public KeyEvent handleKeyEvent(KeyEvent event) { + boolean virtualKeysEnabled = LineageSettings.System.getIntForUser( + mContext.getContentResolver(), + LineageSettings.System.FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) != 0; + boolean fingerprintHomeButtonEnabled = FileUtils.isFileReadable(FP_HOME_NODE) && + FileUtils.readOneLine(FP_HOME_NODE).equals("1"); + + if (!hasSetupCompleted()) { + return event; + } + + if (event.getKeyCode() == KeyEvent.KEYCODE_HOME) { + if (event.getScanCode() == 96) { + if (DEBUG) Log.d(TAG, "Fingerprint home button tapped"); + return virtualKeysEnabled ? null : event; + } + if (event.getScanCode() == 102) { + if (DEBUG) Log.d(TAG, "Mechanical home button pressed"); + return sScreenTurnedOn && + (virtualKeysEnabled || fingerprintHomeButtonEnabled) ? null : event; + } + } + return event; + } + + private boolean hasSetupCompleted() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0) != 0; + } +} diff --git a/configpanel/src/org/lineageos/settings/device/Startup.java b/configpanel/src/org/lineageos/settings/device/Startup.java new file mode 100644 index 0000000..4311cb5 --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/Startup.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * (C) 2017-2018 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.SharedPreferences; +import android.support.v7.preference.PreferenceManager; +import android.util.Log; + +import org.lineageos.internal.util.FileUtils; + +public class Startup extends BroadcastReceiver { + + private static final String TAG = Startup.class.getSimpleName(); + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (lineageos.content.Intent.ACTION_INITIALIZE_LINEAGE_HARDWARE.equals(action)) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + // Disable button settings if needed + if (!hasButtonProcs()) { + disableComponent(context, ButtonSettingsActivity.class.getName()); + } else { + enableComponent(context, ButtonSettingsActivity.class.getName()); + + // Restore nodes to saved preference values + for (String pref : Constants.sButtonPrefKeys) { + String node, value; + if (Constants.sStringNodePreferenceMap.containsKey(pref)) { + node = Constants.sStringNodePreferenceMap.get(pref); + value = Utils.getPreferenceString(context, pref); + } else { + node = Constants.sBooleanNodePreferenceMap.get(pref); + value = Utils.isPreferenceEnabled(context, pref) ? "1" : "0"; + } + if (!FileUtils.writeLine(node, value)) { + Log.w(TAG, "Write to node " + node + + " failed while restoring saved preference values"); + } + } + + // Send initial broadcasts + final boolean shouldEnablePocketMode = + prefs.getBoolean(Constants.FP_WAKEUP_KEY, false) && + prefs.getBoolean(Constants.FP_POCKETMODE_KEY, false); + Utils.broadcastCustIntent(context, shouldEnablePocketMode); + } + } + } + + static boolean hasButtonProcs() { + return (FileUtils.fileExists(Constants.CYTTSP_BUTTON_SWAP_NODE) || + FileUtils.fileExists(Constants.FP_HOME_KEY_NODE) || + FileUtils.fileExists(Constants.FP_WAKEUP_NODE) || + FileUtils.fileExists(Constants.TOUCHPANEL_BUTTON_SWAP_NODE)); + } + + private void disableComponent(Context context, String component) { + ComponentName name = new ComponentName(context, component); + PackageManager pm = context.getPackageManager(); + pm.setComponentEnabledSetting(name, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + } + + private void enableComponent(Context context, String component) { + ComponentName name = new ComponentName(context, component); + PackageManager pm = context.getPackageManager(); + if (pm.getComponentEnabledSetting(name) + == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { + pm.setComponentEnabledSetting(name, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + } + } +} diff --git a/configpanel/src/org/lineageos/settings/device/Utils.java b/configpanel/src/org/lineageos/settings/device/Utils.java new file mode 100644 index 0000000..9b3b2d7 --- /dev/null +++ b/configpanel/src/org/lineageos/settings/device/Utils.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * (C) 2017 The LineageOS 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. + */ + +package org.lineageos.settings.device; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.UserHandle; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.PreferenceManager; + +public class Utils { + + public static boolean isPreferenceEnabled(Context context, String key) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getBoolean(key, (Boolean) Constants.sNodeDefaultMap.get(key)); + } + + public static String getPreferenceString(Context context, String key) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getString(key, (String) Constants.sNodeDefaultMap.get(key)); + } + + public static void updateDependentPreference(Context context, SwitchPreference b, + String key, boolean shouldSetEnabled) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + boolean prefActualValue = preferences.getBoolean(key, false); + + if (shouldSetEnabled) { + if (Constants.sNodeUserSetValuesMap.get(key) != null && + (Boolean) Constants.sNodeUserSetValuesMap.get(key)[1] && + (Boolean) Constants.sNodeUserSetValuesMap.get(key)[1] != prefActualValue) { + b.setChecked(true); + Constants.sNodeUserSetValuesMap.put(key, new Boolean[]{ prefActualValue, false }); + } + } else { + if (b.isEnabled() && prefActualValue) { + Constants.sNodeUserSetValuesMap.put(key, new Boolean[]{ prefActualValue, true }); + } + b.setEnabled(false); + b.setChecked(false); + } + } + + public static void broadcastCustIntent(Context context, boolean value) { + final Intent intent = new Intent(Constants.CUST_INTENT); + intent.putExtra(Constants.CUST_INTENT_EXTRA, value); + context.sendBroadcastAsUser(intent, UserHandle.CURRENT); + } +} @@ -152,6 +152,10 @@ PRODUCT_PACKAGES += \ init.wlan.sh \ ueventd.qcom.rc +# ConfigPanel +PRODUCT_PACKAGES += \ + ConfigPanel + # Display PRODUCT_PACKAGES += \ android.hardware.graphics.allocator@2.0-impl \ |