shamu: vibrator tuning settings
- values taken from CyanogenMod
Change-Id: Ia5c7d8b563a9d34c1f30780222cdd0d0b616d5fe
diff --git a/BoardConfigEV.mk b/BoardConfigEV.mk
index 0da0d52..9155b39 100644
--- a/BoardConfigEV.mk
+++ b/BoardConfigEV.mk
@@ -1,3 +1,6 @@
+#Device Settings
+BOARD_DEVICE_SETTINGS := device/moto/shamu/DeviceSettings
+
# Disable Modules
TARGET_KERNEL_NO_MODULES := true
diff --git a/DeviceSettings/res/layout/preference_dialog_vibrator_tuning.xml b/DeviceSettings/res/layout/preference_dialog_vibrator_tuning.xml
new file mode 100644
index 0000000..baa255f
--- /dev/null
+++ b/DeviceSettings/res/layout/preference_dialog_vibrator_tuning.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Evervolv 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.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:paddingBottom="20dip">
+
+ <TextView android:id="@+id/vibrator_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/vibrator_tuning_title"
+ android:paddingTop="10dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" />
+ <TextView android:id="@+id/vibrator_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" />
+ <SeekBar android:id="@+id/vibrator_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/vibrator_text"
+ android:paddingTop="2dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" />
+
+ <TextView
+ android:id="@+id/textWarn"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/vibrator_seekbar"
+ android:paddingTop="8dip"
+ android:gravity="center"
+ android:text="@string/vibrator_warning"
+ android:textSize="15dp" />
+
+ </RelativeLayout>
+</ScrollView>
diff --git a/DeviceSettings/res/values/strings.xml b/DeviceSettings/res/values/strings.xml
new file mode 100644
index 0000000..038ced0
--- /dev/null
+++ b/DeviceSettings/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2015 The Evervolv 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">
+ <string name="vibrator_title">Vibrator</string>
+ <string name="vibrator_tuning_title">Vibration strength</string>
+ <string name="vibrator_tuning_summary_head">Adjust the strength of the vibration feedback</string>
+ <string name="vibrator_warning">Values higher than %1$d are not recommended</string>
+ <string name="defaults_button">Reset to default</string>
+</resources>
diff --git a/DeviceSettings/res/xml/device_haptic.xml b/DeviceSettings/res/xml/device_haptic.xml
new file mode 100644
index 0000000..6d6dbf0
--- /dev/null
+++ b/DeviceSettings/res/xml/device_haptic.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Evervolv 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">
+ <PreferenceCategory
+ android:title="@string/vibrator_title">
+ <com.evervolv.toolbox.custom.VibratorTuningPreference
+ android:key="vibrator_tuning"
+ android:title="@string/vibrator_tuning_title"
+ android:dialogTitle="@string/vibrator_tuning_title" />
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/DeviceSettings/src/com/evervolv/toolbox/custom/VibratorTuningPreference.java b/DeviceSettings/src/com/evervolv/toolbox/custom/VibratorTuningPreference.java
new file mode 100644
index 0000000..300908e
--- /dev/null
+++ b/DeviceSettings/src/com/evervolv/toolbox/custom/VibratorTuningPreference.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2011-2013 The CyanogenMod Project
+ * Poritions Copyright (C) 2015 The Evervolv 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 com.evervolv.toolbox.custom;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.graphics.Color;
+import android.graphics.LightingColorFilter;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.Bundle;
+import android.os.Vibrator;
+import android.preference.DialogPreference;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Button;
+
+import java.lang.Math;
+import java.text.DecimalFormat;
+
+import com.evervolv.toolbox.R;
+import com.evervolv.toolbox.misc.FileUtil;
+
+/**
+ * Special preference type that allows configuration of vibrator intensity
+ */
+public class VibratorTuningPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
+ private static final String TAG = "VibratorTuningPreference";
+
+ public static final String FILE_PATH = "/sys/vibrator/pwmvalue";
+ public static final int MAX_VALUE = 127;
+ public static final int WARNING_THRESHOLD = -1;
+ public static final int DEFAULT_VALUE = 100;
+ public static final int MIN_VALUE = 0;
+
+ private SeekBar mSeekBar;
+ private TextView mValue;
+ private TextView mWarning;
+
+ private String mOriginalValue;
+ private int mOriginalPercent;
+
+ private Drawable mProgressDrawable;
+ private Drawable mProgressThumb;
+ private LightingColorFilter mRedFilter;
+
+ public VibratorTuningPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setDialogLayoutResource(R.layout.preference_dialog_vibrator_tuning);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.defaults_button, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mSeekBar = (SeekBar) view.findViewById(R.id.vibrator_seekbar);
+ mValue = (TextView) view.findViewById(R.id.vibrator_value);
+ mWarning = (TextView) view.findViewById(R.id.textWarn);
+
+ if (WARNING_THRESHOLD > 0) {
+ String strWarnMsg = getContext().getResources().getString(
+ R.string.vibrator_warning, strengthToPercent(WARNING_THRESHOLD));
+ mWarning.setText(strWarnMsg);
+ } else if (mWarning != null) {
+ mWarning.setVisibility(View.GONE);
+ }
+
+ Drawable progressDrawable = mSeekBar.getProgressDrawable();
+ if (progressDrawable instanceof LayerDrawable) {
+ LayerDrawable ld = (LayerDrawable) progressDrawable;
+ mProgressDrawable = ld.findDrawableByLayerId(android.R.id.progress);
+ }
+ mProgressThumb = mSeekBar.getThumb();
+ mRedFilter = new LightingColorFilter(Color.BLACK,
+ getContext().getResources().getColor(android.R.color.holo_red_light));
+
+ mOriginalValue = FileUtil.fileReadOneLine(FILE_PATH);
+ mOriginalPercent = strengthToPercent(Integer.parseInt(mOriginalValue));
+
+ mSeekBar.setOnSeekBarChangeListener(this);
+ mSeekBar.setProgress(Integer.valueOf(mOriginalPercent));
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mSeekBar.setProgress(strengthToPercent(DEFAULT_VALUE));
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult) {
+ Editor editor = getEditor();
+
+ int strength = percentToStrength(mSeekBar.getProgress());
+ editor.putString(FILE_PATH, String.valueOf(strength));
+ editor.commit();
+ } else {
+ FileUtil.fileWriteOneLine(FILE_PATH, String.valueOf(mOriginalPercent));
+ }
+ }
+
+ public static void restore(Context context) {
+ if (!isSupported(FILE_PATH)) {
+ return;
+ }
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ final String value = prefs.getString(FILE_PATH, null);
+
+ if (value != null) {
+ Log.d(TAG, "Restoring vibration setting: " + value);
+ FileUtil.fileWriteOneLine(FILE_PATH, value);
+ }
+ }
+
+ public static boolean isSupported(String filePath) {
+ return FileUtil.fileExists(filePath);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ boolean shouldWarn = WARNING_THRESHOLD > 0 && progress >= strengthToPercent(WARNING_THRESHOLD);
+ if (mProgressDrawable != null) {
+ mProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null);
+ }
+ if (mProgressThumb != null) {
+ mProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null);
+ }
+ FileUtil.fileWriteOneLine(FILE_PATH, String.valueOf(percentToStrength(progress)));
+ mValue.setText(String.format("%d%%", progress));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ Vibrator vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ vib.vibrate(200);
+ }
+
+ /**
+ * Convert vibrator strength to percent
+ */
+ public static int strengthToPercent(int strength) {
+ double maxValue = MAX_VALUE;
+ double minValue = MIN_VALUE;
+
+ double percent = (strength - minValue) * (100 / (maxValue - minValue));
+
+ if (percent > 100)
+ percent = 100;
+ else if (percent < 0)
+ percent = 0;
+
+ return (int) percent;
+ }
+
+ /**
+ * Convert percent to vibrator strength
+ */
+ public static int percentToStrength(int percent) {
+ int strength = Math.round((((MAX_VALUE - MIN_VALUE) * percent) / 100) + MIN_VALUE);
+
+ if (strength > MAX_VALUE)
+ strength = MAX_VALUE;
+ else if (strength < MIN_VALUE)
+ strength = MIN_VALUE;
+
+ return strength;
+ }
+
+}
diff --git a/DeviceSettings/src/com/evervolv/toolbox/fragments/DeviceHaptic.java b/DeviceSettings/src/com/evervolv/toolbox/fragments/DeviceHaptic.java
new file mode 100644
index 0000000..fc2b668
--- /dev/null
+++ b/DeviceSettings/src/com/evervolv/toolbox/fragments/DeviceHaptic.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012-2013 The CyanogenMod Project
+ * Poritions Copyright (C) 2015 The Evervolv 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 com.evervolv.toolbox.fragments;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+
+import com.evervolv.toolbox.R;
+import com.evervolv.toolbox.Toolbox;
+import com.evervolv.toolbox.custom.VibratorTuningPreference;
+import com.evervolv.toolbox.misc.FileUtil;
+
+public class DeviceHaptic extends DeviceSettingFragment {
+
+ private static final String TAG = "DeviceSettings_Haptic";
+ public static final String KEY_VIBRATOR_TUNING = "vibrator_tuning";
+
+ private VibratorTuningPreference mVibratorTuning;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Resources res = getResources();
+
+ addPreferencesFromResource(R.xml.device_haptic);
+
+ mVibratorTuning = (VibratorTuningPreference) findPreference(
+ KEY_VIBRATOR_TUNING);
+ mVibratorTuning.setEnabled(Toolbox.isEnabled(getActivity()));
+ }
+
+ @Override
+ public void restore(Context context, boolean toolboxEnabled) {
+ if (mVibratorTuning != null) {
+ mVibratorTuning.setEnabled(toolboxEnabled);
+ }
+ if (toolboxEnabled) {
+ VibratorTuningPreference.restore(context);
+ } else {
+ FileUtil.fileWriteOneLine(VibratorTuningPreference.FILE_PATH,
+ Integer.toString(VibratorTuningPreference.DEFAULT_VALUE));
+ }
+ }
+
+}
diff --git a/init.shamu.rc b/init.shamu.rc
index 62074d8..c36a5f9 100644
--- a/init.shamu.rc
+++ b/init.shamu.rc
@@ -341,6 +341,11 @@
mkdir /data/adspd 0770 media media
mkdir /data/adspd/1 0770 media media
+ # Vibrator permissions
+ chown root system /sys/vibrator/pwmvalue
+ chmod 0664 /sys/vibrator/pwmvalue
+ restorecon /sys/vibrator/pwmvalue
+
on property:init.svc.wpa_supplicant=stopped
stop dhcpcd
diff --git a/sepolicy/file.te b/sepolicy/file.te
index 0afbe76..00c4d32 100644
--- a/sepolicy/file.te
+++ b/sepolicy/file.te
@@ -43,3 +43,6 @@
# Define cnd socket and data file type
type cnd_socket, file_type;
type cnd_data_file, file_type;
+
+# for Settings' access to VibratorHW
+type sysfs_vibrator, fs_type, sysfs_type;
diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts
index 81fb4b4..9f4b840 100644
--- a/sepolicy/file_contexts
+++ b/sepolicy/file_contexts
@@ -160,3 +160,6 @@
# CNE
/dev/socket/cnd u:object_r:cnd_socket:s0
/system/bin/cnd u:object_r:cnd_exec:s0
+
+# for Settings' access to VibratorHW
+/sys/vibrator/pwmvalue u:object_r:sysfs_vibrator:s0
diff --git a/sepolicy/system_app.te b/sepolicy/system_app.te
index a6bef97..d85bf81 100644
--- a/sepolicy/system_app.te
+++ b/sepolicy/system_app.te
@@ -8,3 +8,6 @@
#CNE
allow system_app cne_service:service_manager add;
unix_socket_connect(system_app, cnd, cnd);
+
+# for Settings' access to VibratorHW
+allow system_app sysfs_vibrator:file rw_file_perms;