/*
* Copyright (C) 2013 The CyanogenMod Project
* Modifications Copyright (C) 2013 - 2014 Alexander "Evisceration" Martinz
*
* 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.namelessrom.devicecontrol.preferences.hardware;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.os.Vibrator;
import android.preference.DialogPreference;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import org.namelessrom.devicecontrol.App;
import org.namelessrom.devicecontrol.R;
import org.namelessrom.devicecontrol.models.BootupConfig;
import org.namelessrom.devicecontrol.modules.bootup.BootupItem;
import org.namelessrom.devicecontrol.utils.Utils;
import at.amartinz.execution.RootShell;
import timber.log.Timber;
public class VibratorIntensity extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
private final Vibrator vib;
private static String[] paths;
private String path;
private int max;
private int min;
private int defValue;
private int threshold;
private SeekBar mSeekBar;
private TextView mValue;
private String mOriginalValue;
private Drawable mProgressDrawable;
private Drawable mProgressThumb = null;
private static LightingColorFilter mRedFilter = null;
public VibratorIntensity(final Context context, final AttributeSet attrs) {
super(context, attrs);
vib = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
setupValues(context);
setLayoutResource(R.layout.preference);
setDialogLayoutResource(R.layout.preference_dialog_vibrator_tuning);
}
private void setupValues(final Context context) {
// get all the values
final Resources res = context.getResources();
if (paths == null) {
paths = res.getStringArray(R.array.hardware_vibrator_paths);
}
final String[] maxs = res.getStringArray(R.array.hardware_vibrator_maximum);
final String[] mins = res.getStringArray(R.array.hardware_vibrator_minimum);
final String[] maxPaths = res.getStringArray(R.array.hardware_vibrator_maximum_path);
final String[] minPaths = res.getStringArray(R.array.hardware_vibrator_minimum_path);
final String[] defs = res.getStringArray(R.array.hardware_vibrator_default);
final String[] thresholds = res.getStringArray(R.array.hardware_vibrator_threshold);
final int length = paths.length;
for (int i = 0; i < length; i++) {
// if the file exists, set up the values
if (Utils.fileExists(paths[i])) {
// our existing path
path = paths[i];
// if we have a path for maximum, use it. else use the maximum defined value
if (TextUtils.equals("-", maxPaths[i])) {
max = Utils.parseInt(maxs[i]);
} else {
max = (Utils.parseInt(Utils.readOneLine(maxPaths[i])));
}
// same for minimum
if (TextUtils.equals("-", minPaths[i])) {
min = Utils.parseInt(mins[i]);
} else {
min = (Utils.parseInt(Utils.readOneLine(minPaths[i])));
}
// we can also use max or min for the default value
if (TextUtils.equals("max", defs[i])) {
defValue = max;
} else if (TextUtils.equals("min", defs[i])) {
defValue = min;
} else {
defValue = Utils.parseInt(defs[i]);
}
// if the threshold is -1, we should not show the warning dialog
threshold = Utils.parseInt(thresholds[i]);
// and get out of here
break;
}
}
}
@Override protected void onBindDialogView(@NonNull final View view) {
super.onBindDialogView(view);
final String def = String.format(getContext().getString(R.string.string_default) + ": %s",
String.valueOf(strengthToPercent(defValue)) + "%");
((TextView) view.findViewById(R.id.vibrator_value_def)).setText(def);
mSeekBar = (SeekBar) view.findViewById(R.id.vibrator_seekbar);
mValue = (TextView) view.findViewById(R.id.vibrator_value);
final TextView mWarning = (TextView) view.findViewById(R.id.textWarn);
if (threshold != -1) {
final String strWarnMsg = getContext().getString(
R.string.vibrator_warning, strengthToPercent(threshold) - 1);
mWarning.setText(strWarnMsg);
} else {
mWarning.setVisibility(View.GONE);
}
final Drawable progressDrawable = mSeekBar.getProgressDrawable();
if (progressDrawable instanceof LayerDrawable) {
LayerDrawable ld = (LayerDrawable) progressDrawable;
mProgressDrawable = ld.findDrawableByLayerId(android.R.id.progress);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mProgressThumb = mSeekBar.getThumb();
}
if (mRedFilter == null) {
mRedFilter = new LightingColorFilter(Color.BLACK,
getContext().getResources().getColor(android.R.color.holo_red_light));
}
// Read the current value from sysfs in case user wants to dismiss his changes
mOriginalValue = Utils.readOneLine(path);
// Restore percent value from SharedPreferences object
final BootupItem item = BootupConfig.get().getItemByName("vibrator_tuning");
final String value = (item != null) ? item.value : null;
final int percent = strengthToPercent(value != null ? Utils.parseInt(mOriginalValue) : defValue);
Timber.v("value: %s, percent: %s", value, percent);
mSeekBar.setOnSeekBarChangeListener(this);
mSeekBar.setProgress(percent);
view.findViewById(R.id.vibrator_test).setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
if (vib != null) {
vib.cancel();
vib.vibrate(250);
}
}
});
}
@Override protected void onDialogClosed(final boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
BootupConfig.setBootup(new BootupItem(
BootupConfig.CATEGORY_DEVICE, "vibrator_tuning",
path, String.valueOf(percentToStrength(mSeekBar.getProgress())), true));
} else {
RootShell.fireAndForget(Utils.getWriteCommand(path, String.valueOf(mOriginalValue)));
}
}
@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
final boolean shouldWarn = (threshold != -1 && progress >= strengthToPercent(threshold));
if (mProgressDrawable != null) {
mProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null);
}
if (mProgressThumb != null) {
mProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null);
}
mValue.setText(String.format("%d%%", progress));
}
@Override public void onStartTrackingTouch(SeekBar seekBar) { }
@Override public void onStopTrackingTouch(SeekBar seekBar) {
final String value = String.valueOf(percentToStrength(seekBar.getProgress()));
RootShell.fireAndForget(Utils.getWriteCommand(path, value));
}
/**
* Convert vibrator strength to percent
*/
private int strengthToPercent(final int strength) {
final double percent = (strength - min) * (100 / (max - min != 0 ? max - min : 1));
if (percent > 100) { return 100; } else if (percent < 0) { return 0; }
return (int) percent;
}
/**
* Convert percent to vibrator strength
*/
private int percentToStrength(final int percent) {
final int strength = Math.round((((max - min) * percent) / 100) + min);
if (strength > max) {
return max;
} else if (strength < min) {
return min;
}
return strength;
}
public static boolean isSupported() {
if (paths == null) {
paths = App.get().getStringArray(R.array.hardware_vibrator_paths);
}
return (Utils.fileExists(paths));
}
}