mirror of
https://github.com/chararomandroid/android_device_samsung_a20
synced 2026-08-22 20:15:32 -04:00
unversal7885: SamsungParts: Convert to Kotlin
This commit is contained in:
parent
3eeab18801
commit
e3848cdb11
60 changed files with 1657 additions and 2217 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
android_app {
|
android_app {
|
||||||
name: "SamsungParts",
|
name: "SamsungParts",
|
||||||
srcs: [
|
srcs: [
|
||||||
"src/**/*.java",
|
|
||||||
"src/**/*.kt",
|
"src/**/*.kt",
|
||||||
],
|
],
|
||||||
platform_apis: true,
|
platform_apis: true,
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ Java_com_eurekateam_samsungextras_interfaces_Battery_getChargeSysfs
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_eurekateam_samsungextras_interfaces_Battery_setFastCharge(JNIEnv *env, __unused jclass obj,
|
Java_com_eurekateam_samsungextras_interfaces_Battery_setFastCharge(JNIEnv *env, __unused jobject obj,
|
||||||
jint enable) {
|
jint enable) {
|
||||||
android::sp<IBattery> service = IBattery::getService();
|
android::sp<IBattery> service = IBattery::getService();
|
||||||
if (enable == 1){
|
if (enable == 1){
|
||||||
|
|
@ -52,9 +52,7 @@ jclass obj) {
|
||||||
}
|
}
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_eurekateam_samsungextras_interfaces_Battery_getGeneralBatteryStats(JNIEnv *env,
|
Java_com_eurekateam_samsungextras_interfaces_Battery_getGeneralBatteryStats(JNIEnv *env,__unused jobject obj, jint id) {
|
||||||
__unused
|
|
||||||
jclass obj, jint id) {
|
|
||||||
/**
|
/**
|
||||||
* id:
|
* id:
|
||||||
* 1 = BATTERY_CAPACITY_MAX
|
* 1 = BATTERY_CAPACITY_MAX
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using android::sp;
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_eurekateam_samsungextras_interfaces_Flashlight_setFlash(JNIEnv *env, __unused jclass obj,
|
Java_com_eurekateam_samsungextras_interfaces_Flashlight_setFlash(JNIEnv *env, __unused jobject obj,
|
||||||
jint value) {
|
jint value) {
|
||||||
android::sp<IFlashlight> service = IFlashlight::getService();
|
android::sp<IFlashlight> service = IFlashlight::getService();
|
||||||
service->setFlashlightEnable(Enable::ENABLE);
|
service->setFlashlightEnable(Enable::ENABLE);
|
||||||
|
|
@ -55,14 +55,10 @@ Java_com_eurekateam_samsungextras_interfaces_Flashlight_setFlash(JNIEnv *env, __
|
||||||
}
|
}
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_eurekateam_samsungextras_interfaces_Flashlight_getFlash(JNIEnv *env, jclass clazz,
|
Java_com_eurekateam_samsungextras_interfaces_Flashlight_getFlash(JNIEnv *env, jobject clazz,
|
||||||
jint isA10) {
|
jint isA10) {
|
||||||
android::sp<IFlashlight> service = IFlashlight::getService();
|
android::sp<IFlashlight> service = IFlashlight::getService();
|
||||||
int ret;
|
int ret;
|
||||||
if(isA10 == 1) {
|
ret = service->readFlashlightstats(Device::A10);
|
||||||
ret = service->readFlashlightstats(Device::A10);
|
|
||||||
}else{
|
|
||||||
ret = service->readFlashlightstats(Device::NOTA10);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB |
|
|
@ -23,7 +23,8 @@
|
||||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
android:background="?android:attr/activatedBackgroundIndicator"
|
android:background="?android:attr/activatedBackgroundIndicator"
|
||||||
android:clipToPadding="false">
|
android:clipToPadding="false"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@android:id/icon_frame"
|
android:id="@android:id/icon_frame"
|
||||||
|
|
@ -45,7 +46,7 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
|
|
@ -127,11 +128,11 @@
|
||||||
android:id="@+id/seekbar"
|
android:id="@+id/seekbar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginEnd="3dp"
|
android:layout_marginEnd="3dp"
|
||||||
android:layout_toEndOf="@id/minus"
|
android:layout_toEndOf="@id/minus"
|
||||||
android:layout_toStartOf="@id/plus"
|
android:layout_toStartOf="@id/plus"
|
||||||
android:layout_centerVertical="true" />
|
android:layout_centerVertical="true"
|
||||||
|
android:orientation="horizontal" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,9 @@
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Title"
|
android:textAppearance="@android:style/TextAppearance.Material.Title"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:text="@string/switch_bar_on" />
|
android:text="@string/switch_bar_on" />
|
||||||
|
|
||||||
<Switch
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@android:id/switch_widget"
|
android:id="@android:id/switch_widget"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="dolby_pref"
|
android:key="dolby_pref"
|
||||||
android:title="@string/dolby_title"
|
android:title="@string/dolby_title"
|
||||||
android:icon="@drawable/dolby"
|
android:icon="@drawable/ic_speaker_cleaner_icon"
|
||||||
android:summary="@string/dolby_summary"/>
|
android:summary="@string/dolby_summary"/>
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.interfaces.GPU;
|
|
||||||
|
|
||||||
|
|
||||||
public class BootReceiver extends BroadcastReceiver {
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
|
|
||||||
if (context != null) {
|
|
||||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
|
|
||||||
boolean fpsenabled = sharedPrefs.getBoolean(DeviceSettings.PREF_KEY_FPS_INFO, false);
|
|
||||||
if (fpsenabled) {
|
|
||||||
context.startService(new Intent(context, FPSInfoService.class));
|
|
||||||
}
|
|
||||||
boolean gpuenabled = sharedPrefs.getBoolean(DeviceSettings.PREF_GPUEXYNOS, false);
|
|
||||||
if (!gpuenabled){
|
|
||||||
GPU.setGPU(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.eurekateam.samsungextras.interfaces.GPU
|
||||||
|
|
||||||
|
class BootReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (intent.action.equals(Intent.ACTION_BOOT_COMPLETED, ignoreCase = true)) {
|
||||||
|
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
val fpsenabled = sharedPrefs.getBoolean(DeviceSettings.PREF_KEY_FPS_INFO, false)
|
||||||
|
if (fpsenabled) {
|
||||||
|
context.startService(Intent(context, FPSInfoService::class.java))
|
||||||
|
}
|
||||||
|
val gpuenabled = sharedPrefs.getBoolean(DeviceSettings.PREF_GPUEXYNOS, true)
|
||||||
|
if (gpuenabled) {
|
||||||
|
GPU.GPU = 1
|
||||||
|
}else{
|
||||||
|
GPU.GPU = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceFragment;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.battery.BatteryActivity;
|
|
||||||
import com.eurekateam.samsungextras.flashlight.FlashLightActivity;
|
|
||||||
import com.eurekateam.samsungextras.interfaces.GPU;
|
|
||||||
import com.eurekateam.samsungextras.interfaces.SELinux;
|
|
||||||
import com.eurekateam.samsungextras.speaker.ClearSpeakerActivity;
|
|
||||||
|
|
||||||
public class DeviceSettings extends PreferenceFragment implements
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
public static final String PREF_KEY_FPS_INFO = "fps_info";
|
|
||||||
private static final String PREF_CLEAR_SPEAKER = "clear_speaker_settings";
|
|
||||||
private static final String PREF_FLASHLIGHT = "flashlight_settings";
|
|
||||||
public static final String PREF_GPUEXYNOS = "gpuexynos_settings";
|
|
||||||
private static final String PREF_SELINUX = "selinux_settings";
|
|
||||||
public static final String PREF_BATTERY = "battery_settings";
|
|
||||||
|
|
||||||
public DeviceSettings() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
System.loadLibrary("samsungparts_jni");
|
|
||||||
setPreferencesFromResource(R.xml.preferences_samsung_parts, rootKey);
|
|
||||||
Context mContext = this.getContext();
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
|
|
||||||
Preference mClearSpeakerPref = findPreference(PREF_CLEAR_SPEAKER);
|
|
||||||
assert mClearSpeakerPref != null;
|
|
||||||
mClearSpeakerPref.setOnPreferenceClickListener(preference -> {
|
|
||||||
Intent intent = new Intent(getActivity().getApplicationContext(), ClearSpeakerActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
SwitchPreference mFpsInfo = findPreference(PREF_KEY_FPS_INFO);
|
|
||||||
assert mFpsInfo != null;
|
|
||||||
mFpsInfo.setChecked(prefs.getBoolean(PREF_KEY_FPS_INFO, false));
|
|
||||||
mFpsInfo.setOnPreferenceChangeListener(this);
|
|
||||||
|
|
||||||
SwitchPreference mGPUExynos = findPreference(PREF_GPUEXYNOS);
|
|
||||||
assert mGPUExynos != null;
|
|
||||||
mGPUExynos.setChecked(GPU.getGPU() == 1);
|
|
||||||
mGPUExynos.setOnPreferenceChangeListener(this);
|
|
||||||
|
|
||||||
Preference mSELinux = findPreference(PREF_SELINUX);
|
|
||||||
assert mSELinux != null;
|
|
||||||
mSELinux.setOnPreferenceClickListener(preference -> {
|
|
||||||
Toast.makeText(getContext(), SELinux.getSELinux() == 1 ?
|
|
||||||
"SELinux is in enforcing state." :
|
|
||||||
"SELinux is in permissive state.",
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
Preference mFlashLight = findPreference(PREF_FLASHLIGHT);
|
|
||||||
assert mFlashLight != null;
|
|
||||||
mFlashLight.setOnPreferenceClickListener(preference -> {
|
|
||||||
Intent intent = new Intent(getActivity().getApplicationContext(), FlashLightActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
Preference mFastCharge = findPreference(PREF_BATTERY);
|
|
||||||
assert mFastCharge != null;
|
|
||||||
mFastCharge.setOnPreferenceClickListener(preference -> {
|
|
||||||
Intent intent = new Intent(getActivity().getApplicationContext(), BatteryActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
|
||||||
final String key = preference.getKey();
|
|
||||||
switch (key) {
|
|
||||||
case PREF_KEY_FPS_INFO:
|
|
||||||
boolean fps_enabled = (Boolean) value;
|
|
||||||
Intent fpsinfo = new Intent(this.getContext(), FPSInfoService.class);
|
|
||||||
if (fps_enabled) {
|
|
||||||
this.getContext().startService(fpsinfo);
|
|
||||||
} else {
|
|
||||||
this.getContext().stopService(fpsinfo);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PREF_GPUEXYNOS:
|
|
||||||
boolean gpu_enabled = (Boolean) value;
|
|
||||||
GPU.setGPU(gpu_enabled ? 1 : 0);
|
|
||||||
Toast.makeText(getContext(), gpu_enabled ? "GPU Throttling is now enabled."
|
|
||||||
: "GPU Throttling is now disabled.",
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragment
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import com.eurekateam.samsungextras.battery.BatteryActivity
|
||||||
|
import com.eurekateam.samsungextras.flashlight.FlashLightActivity
|
||||||
|
import com.eurekateam.samsungextras.interfaces.GPU.GPU
|
||||||
|
import com.eurekateam.samsungextras.interfaces.SELinux.SELinux
|
||||||
|
import com.eurekateam.samsungextras.speaker.ClearSpeakerActivity
|
||||||
|
|
||||||
|
class DeviceSettings : PreferenceFragment(), Preference.OnPreferenceChangeListener {
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
System.loadLibrary("samsungparts_jni")
|
||||||
|
setPreferencesFromResource(R.xml.preferences_samsung_parts, rootKey)
|
||||||
|
val mContext = this.context
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(mContext)
|
||||||
|
val mClearSpeakerPref = findPreference<Preference>(PREF_CLEAR_SPEAKER)!!
|
||||||
|
mClearSpeakerPref.onPreferenceClickListener =
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
val intent = Intent(activity.applicationContext, ClearSpeakerActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
val mFpsInfo = findPreference<SwitchPreference>(PREF_KEY_FPS_INFO)!!
|
||||||
|
mFpsInfo.isChecked = prefs.getBoolean(PREF_KEY_FPS_INFO, false)
|
||||||
|
mFpsInfo.onPreferenceChangeListener = this
|
||||||
|
val mGPUExynos = findPreference<SwitchPreference>(PREF_GPUEXYNOS)!!
|
||||||
|
mGPUExynos.isChecked = GPU == 1
|
||||||
|
mGPUExynos.onPreferenceChangeListener = this
|
||||||
|
val mSELinux = findPreference<Preference>(PREF_SELINUX)!!
|
||||||
|
mSELinux.onPreferenceClickListener =
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
if (SELinux == 1) "SELinux is in enforcing state." else "SELinux is in permissive state.",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
val mFlashLight = findPreference<Preference>(PREF_FLASHLIGHT)!!
|
||||||
|
mFlashLight.onPreferenceClickListener =
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
val intent = Intent(activity.applicationContext, FlashLightActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
val mFastCharge = findPreference<Preference>(PREF_BATTERY)!!
|
||||||
|
mFastCharge.onPreferenceClickListener =
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
val intent = Intent(activity.applicationContext, BatteryActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, value: Any): Boolean {
|
||||||
|
when (preference.key) {
|
||||||
|
PREF_KEY_FPS_INFO -> {
|
||||||
|
val fps_enabled = value as Boolean
|
||||||
|
val fpsinfo = Intent(this.context, FPSInfoService::class.java)
|
||||||
|
if (fps_enabled) {
|
||||||
|
this.context.startService(fpsinfo)
|
||||||
|
} else {
|
||||||
|
this.context.stopService(fpsinfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PREF_GPUEXYNOS -> {
|
||||||
|
val gpu_enabled = value as Boolean
|
||||||
|
GPU = if (gpu_enabled) 1 else 0
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
if (gpu_enabled) "GPU Throttling is now enabled." else "GPU Throttling is now disabled.",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PREF_KEY_FPS_INFO = "fps_info"
|
||||||
|
private const val PREF_CLEAR_SPEAKER = "clear_speaker_settings"
|
||||||
|
private const val PREF_FLASHLIGHT = "flashlight_settings"
|
||||||
|
const val PREF_GPUEXYNOS = "gpuexynos_settings"
|
||||||
|
private const val PREF_SELINUX = "selinux_settings"
|
||||||
|
const val PREF_BATTERY = "battery_settings"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
public class DeviceSettingsActivity extends Activity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
|
|
||||||
DeviceSettings mDeviceSettingsFragment;
|
|
||||||
if (fragment == null) {
|
|
||||||
mDeviceSettingsFragment = new DeviceSettings();
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.add(android.R.id.content, mDeviceSettingsFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import com.android.internal.R.id.content
|
||||||
|
import com.android.internal.R.id.home
|
||||||
|
|
||||||
|
class DeviceSettingsActivity : Activity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
|
val fragment = fragmentManager.findFragmentById(content)
|
||||||
|
val mDeviceSettingsFragment: DeviceSettings
|
||||||
|
if (fragment == null) {
|
||||||
|
mDeviceSettingsFragment = DeviceSettings()
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(content, mDeviceSettingsFragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == home) {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package com.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.service.quicksettings.Tile;
|
|
||||||
import android.service.quicksettings.TileService;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.dolby.DolbyCore;
|
|
||||||
|
|
||||||
public class DolbyTile extends TileService {
|
|
||||||
private boolean isRunning;
|
|
||||||
DolbyCore dolbyCore = new DolbyCore();
|
|
||||||
@Override
|
|
||||||
public void onStartListening() {
|
|
||||||
super.onStartListening();
|
|
||||||
isRunning = dolbyCore.isRunning();
|
|
||||||
updateTile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick() {
|
|
||||||
if (isRunning) {
|
|
||||||
dolbyCore.stopDolbyEffect();
|
|
||||||
}else{
|
|
||||||
dolbyCore.justStartOnly();
|
|
||||||
}
|
|
||||||
isRunning = !isRunning;
|
|
||||||
updateTile();
|
|
||||||
}
|
|
||||||
private void updateTile() {
|
|
||||||
final Tile tile = getQsTile();
|
|
||||||
tile.setState(isRunning ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
|
||||||
tile.updateTile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.service.quicksettings.Tile
|
||||||
|
import android.service.quicksettings.TileService
|
||||||
|
import com.eurekateam.samsungextras.dolby.DolbyCore
|
||||||
|
|
||||||
|
class DolbyTile : TileService() {
|
||||||
|
private var isRunning = false
|
||||||
|
private var dolbyCore = DolbyCore()
|
||||||
|
override fun onStartListening() {
|
||||||
|
super.onStartListening()
|
||||||
|
isRunning = dolbyCore.isRunning()
|
||||||
|
updateTile()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick() {
|
||||||
|
if (isRunning) {
|
||||||
|
dolbyCore.stopDolbyEffect()
|
||||||
|
} else {
|
||||||
|
dolbyCore.justStartOnly()
|
||||||
|
}
|
||||||
|
isRunning = !isRunning
|
||||||
|
updateTile()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTile() {
|
||||||
|
val tile = qsTile
|
||||||
|
tile.state =
|
||||||
|
if (isRunning) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
|
||||||
|
tile.updateTile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,282 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.ServiceManager;
|
|
||||||
import android.service.dreams.DreamService;
|
|
||||||
import android.service.dreams.IDreamManager;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
|
|
||||||
public class FPSInfoService extends Service {
|
|
||||||
private View mView;
|
|
||||||
private Thread mCurFPSThread;
|
|
||||||
private static SurfaceFlingerFPS surfaceFlingerFPS;
|
|
||||||
private final String TAG = "FPSInfoService";
|
|
||||||
private String mFps = null;
|
|
||||||
|
|
||||||
private IDreamManager mDreamManager;
|
|
||||||
|
|
||||||
private class FPSView extends View {
|
|
||||||
private final Paint mOnlinePaint;
|
|
||||||
private final float mAscent;
|
|
||||||
private int mMaxWidth = 0;
|
|
||||||
|
|
||||||
private int mNeededWidth;
|
|
||||||
private int mNeededHeight;
|
|
||||||
|
|
||||||
private boolean mDataAvail;
|
|
||||||
|
|
||||||
private final Handler mCurFPSHandler = new Handler(Looper.getMainLooper()) {
|
|
||||||
public void handleMessage(Message msg) {
|
|
||||||
if (msg.obj == null || msg.what != 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String msgData = (String) msg.obj;
|
|
||||||
mFps = msgData + " FPS";
|
|
||||||
mDataAvail = true;
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FPSView(Context c) {
|
|
||||||
super(c);
|
|
||||||
float density = c.getResources().getDisplayMetrics().density;
|
|
||||||
int paddingPx = Math.round(5 * density);
|
|
||||||
setPadding(paddingPx, paddingPx, paddingPx, paddingPx);
|
|
||||||
setBackgroundColor(Color.argb(0x60, 0, 0, 0));
|
|
||||||
|
|
||||||
final int textSize = Math.round(12 * density);
|
|
||||||
|
|
||||||
Typeface typeface = Typeface.create("monospace", Typeface.NORMAL);
|
|
||||||
|
|
||||||
mOnlinePaint = new Paint();
|
|
||||||
mOnlinePaint.setTypeface(typeface);
|
|
||||||
mOnlinePaint.setAntiAlias(true);
|
|
||||||
mOnlinePaint.setTextSize(textSize);
|
|
||||||
mOnlinePaint.setColor(Color.WHITE);
|
|
||||||
mOnlinePaint.setShadowLayer(5.0f, 0.0f, 0.0f, Color.BLACK);
|
|
||||||
|
|
||||||
mAscent = mOnlinePaint.ascent();
|
|
||||||
mOnlinePaint.descent();
|
|
||||||
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onAttachedToWindow() {
|
|
||||||
super.onAttachedToWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDetachedFromWindow() {
|
|
||||||
super.onDetachedFromWindow();
|
|
||||||
mCurFPSHandler.removeMessages(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
||||||
setMeasuredDimension(resolveSize(mNeededWidth, widthMeasureSpec),
|
|
||||||
resolveSize(mNeededHeight, heightMeasureSpec));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getFPSInfoString() {
|
|
||||||
return mFps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDraw(Canvas canvas) {
|
|
||||||
super.onDraw(canvas);
|
|
||||||
if (!mDataAvail) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int LEFT = getWidth() - 1;
|
|
||||||
|
|
||||||
int y = mPaddingTop - (int) mAscent;
|
|
||||||
|
|
||||||
String s = getFPSInfoString();
|
|
||||||
canvas.drawText(s, LEFT - mPaddingLeft - mMaxWidth,
|
|
||||||
y - 1, mOnlinePaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateDisplay() {
|
|
||||||
if (!mDataAvail) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mOnlinePaint != null) {
|
|
||||||
mMaxWidth = (int) mOnlinePaint.measureText(mFps);
|
|
||||||
}
|
|
||||||
|
|
||||||
int neededWidth = mPaddingLeft + mPaddingRight + mMaxWidth;
|
|
||||||
int neededHeight = mPaddingTop + mPaddingBottom + 40;
|
|
||||||
if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
|
|
||||||
mNeededWidth = neededWidth;
|
|
||||||
mNeededHeight = neededHeight;
|
|
||||||
requestLayout();
|
|
||||||
} else {
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Handler getHandler() {
|
|
||||||
return mCurFPSHandler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thead to monitor fps
|
|
||||||
*/
|
|
||||||
protected static class CurFPSThread extends Thread {
|
|
||||||
private boolean mInterrupt = false;
|
|
||||||
private final Handler mHandler;
|
|
||||||
|
|
||||||
public CurFPSThread(Handler handler) {
|
|
||||||
mHandler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void interrupt() {
|
|
||||||
mInterrupt = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
while (!mInterrupt) {
|
|
||||||
sleep(500);
|
|
||||||
new StringBuilder();
|
|
||||||
String fpsVal = String.valueOf(Math.round(surfaceFlingerFPS.getFps()));
|
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1, fpsVal));
|
|
||||||
}
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
|
|
||||||
mView = new FPSView(this);
|
|
||||||
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
|
||||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
|
||||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
|
||||||
WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
|
|
||||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
|
||||||
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
|
|
||||||
PixelFormat.TRANSLUCENT);
|
|
||||||
params.y = 50;
|
|
||||||
params.gravity = Gravity.START | Gravity.TOP;
|
|
||||||
params.setTitle("FPS Info");
|
|
||||||
surfaceFlingerFPS = SurfaceFlingerFPS.getInstance();
|
|
||||||
startThread();
|
|
||||||
|
|
||||||
mDreamManager = IDreamManager.Stub.asInterface(
|
|
||||||
ServiceManager.checkService(DreamService.DREAM_SERVICE));
|
|
||||||
IntentFilter screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
|
||||||
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
|
||||||
registerReceiver(mScreenStateReceiver, screenStateFilter);
|
|
||||||
|
|
||||||
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
|
|
||||||
wm.addView(mView, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
stopThread();
|
|
||||||
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
|
|
||||||
mView = null;
|
|
||||||
unregisterReceiver(mScreenStateReceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
|
|
||||||
Log.d(TAG, "ACTION_SCREEN_ON " + isDozeMode());
|
|
||||||
if (!isDozeMode()) {
|
|
||||||
startThread();
|
|
||||||
mView.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
|
||||||
Log.d(TAG, "ACTION_SCREEN_OFF");
|
|
||||||
mView.setVisibility(View.GONE);
|
|
||||||
stopThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find is the device is in doze mode
|
|
||||||
* @return true if device is in doze mode, else false
|
|
||||||
*/
|
|
||||||
private boolean isDozeMode() {
|
|
||||||
try {
|
|
||||||
if (mDreamManager != null && mDreamManager.isDreaming()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startThread() {
|
|
||||||
Log.d(TAG, "started CurFPSThread");
|
|
||||||
mCurFPSThread = new CurFPSThread(mView.getHandler());
|
|
||||||
surfaceFlingerFPS.start();
|
|
||||||
mCurFPSThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopThread() {
|
|
||||||
if (mCurFPSThread != null && mCurFPSThread.isAlive()) {
|
|
||||||
Log.d(TAG, "stopping CurFPSThread");
|
|
||||||
surfaceFlingerFPS.stop();
|
|
||||||
mCurFPSThread.interrupt();
|
|
||||||
try {
|
|
||||||
mCurFPSThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mCurFPSThread = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Xiaomi-SM6250 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.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.graphics.*
|
||||||
|
import android.os.*
|
||||||
|
import android.service.dreams.DreamService
|
||||||
|
import android.service.dreams.IDreamManager
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
open class FPSInfoService : Service() {
|
||||||
|
private var mView: View? = null
|
||||||
|
private var mCurFPSThread: Thread? = null
|
||||||
|
private val TAG = "FPSInfoService"
|
||||||
|
private var fPSInfoString: String? = null
|
||||||
|
private var mDreamManager: IDreamManager? = null
|
||||||
|
|
||||||
|
private inner class FPSView(c: Context) : View(c) {
|
||||||
|
private val mOnlinePaint: Paint?
|
||||||
|
private val mAscent: Float
|
||||||
|
private var mMaxWidth = 0
|
||||||
|
private var mNeededWidth = 0
|
||||||
|
private var mNeededHeight = 0
|
||||||
|
private var mDataAvail = false
|
||||||
|
private val mCurFPSHandler: Handler = object : Handler(Looper.getMainLooper()) {
|
||||||
|
override fun handleMessage(msg: Message) {
|
||||||
|
if (msg.obj == null || msg.what != 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val msgData = msg.obj as String
|
||||||
|
fPSInfoString = "$msgData FPS"
|
||||||
|
mDataAvail = true
|
||||||
|
updateDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
mCurFPSHandler.removeMessages(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
setMeasuredDimension(
|
||||||
|
resolveSize(mNeededWidth, widthMeasureSpec),
|
||||||
|
resolveSize(mNeededHeight, heightMeasureSpec)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onDraw(canvas: Canvas) {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
if (!mDataAvail) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val LEFT = width - 1
|
||||||
|
val y = mPaddingTop - mAscent.toInt()
|
||||||
|
val s = fPSInfoString
|
||||||
|
canvas.drawText(
|
||||||
|
s, (LEFT - mPaddingLeft - mMaxWidth).toFloat(), (
|
||||||
|
y - 1).toFloat(), mOnlinePaint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateDisplay() {
|
||||||
|
if (!mDataAvail) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (mOnlinePaint != null) {
|
||||||
|
mMaxWidth = mOnlinePaint.measureText(fPSInfoString).toInt()
|
||||||
|
}
|
||||||
|
val neededWidth = mPaddingLeft + mPaddingRight + mMaxWidth
|
||||||
|
val neededHeight = mPaddingTop + mPaddingBottom + 40
|
||||||
|
if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
|
||||||
|
mNeededWidth = neededWidth
|
||||||
|
mNeededHeight = neededHeight
|
||||||
|
requestLayout()
|
||||||
|
} else {
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHandler(): Handler {
|
||||||
|
return mCurFPSHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val density = c.resources.displayMetrics.density
|
||||||
|
val paddingPx = (5 * density).roundToInt()
|
||||||
|
setPadding(paddingPx, paddingPx, paddingPx, paddingPx)
|
||||||
|
setBackgroundColor(Color.argb(0x60, 0, 0, 0))
|
||||||
|
val textSize = (12 * density).roundToInt()
|
||||||
|
val typeface = Typeface.create("monospace", Typeface.NORMAL)
|
||||||
|
mOnlinePaint = Paint()
|
||||||
|
mOnlinePaint.typeface = typeface
|
||||||
|
mOnlinePaint.isAntiAlias = true
|
||||||
|
mOnlinePaint.textSize = textSize.toFloat()
|
||||||
|
mOnlinePaint.color = Color.WHITE
|
||||||
|
mOnlinePaint.setShadowLayer(5.0f, 0.0f, 0.0f, Color.BLACK)
|
||||||
|
mAscent = mOnlinePaint.ascent()
|
||||||
|
mOnlinePaint.descent()
|
||||||
|
updateDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thead to monitor fps
|
||||||
|
*/
|
||||||
|
protected class CurFPSThread(private val mHandler: Handler) : Thread() {
|
||||||
|
private var mInterrupt = false
|
||||||
|
override fun interrupt() {
|
||||||
|
mInterrupt = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
try {
|
||||||
|
while (!mInterrupt) {
|
||||||
|
sleep(500)
|
||||||
|
StringBuilder()
|
||||||
|
val fpsVal = surfaceFlingerFPS?.fps?.roundToInt().toString()
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(1, fpsVal))
|
||||||
|
}
|
||||||
|
} catch (ignored: InterruptedException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
mView = FPSView(this)
|
||||||
|
val params = WindowManager.LayoutParams(
|
||||||
|
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||||
|
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||||
|
WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
|
||||||
|
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
|
||||||
|
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
|
||||||
|
PixelFormat.TRANSLUCENT
|
||||||
|
)
|
||||||
|
params.y = 50
|
||||||
|
params.gravity = Gravity.START or Gravity.TOP
|
||||||
|
params.title = "FPS Info"
|
||||||
|
surfaceFlingerFPS = SurfaceFlingerFPS.instance
|
||||||
|
startThread()
|
||||||
|
mDreamManager = IDreamManager.Stub.asInterface(
|
||||||
|
ServiceManager.checkService(DreamService.DREAM_SERVICE)
|
||||||
|
)
|
||||||
|
val screenStateFilter = IntentFilter(Intent.ACTION_SCREEN_ON)
|
||||||
|
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||||
|
registerReceiver(mScreenStateReceiver, screenStateFilter)
|
||||||
|
val wm = getSystemService(WINDOW_SERVICE) as WindowManager
|
||||||
|
wm.addView(mView, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
stopThread()
|
||||||
|
(getSystemService(WINDOW_SERVICE) as WindowManager).removeView(mView)
|
||||||
|
mView = null
|
||||||
|
unregisterReceiver(mScreenStateReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mScreenStateReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (intent.action == Intent.ACTION_SCREEN_ON) {
|
||||||
|
Log.d(TAG, "ACTION_SCREEN_ON $isDozeMode")
|
||||||
|
if (!isDozeMode) {
|
||||||
|
startThread()
|
||||||
|
mView!!.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
} else if (intent.action == Intent.ACTION_SCREEN_OFF) {
|
||||||
|
Log.d(TAG, "ACTION_SCREEN_OFF")
|
||||||
|
mView!!.visibility = View.GONE
|
||||||
|
stopThread()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find is the device is in doze mode
|
||||||
|
* @return true if device is in doze mode, else false
|
||||||
|
*/
|
||||||
|
private val isDozeMode: Boolean
|
||||||
|
get() {
|
||||||
|
try {
|
||||||
|
if (mDreamManager != null && mDreamManager!!.isDreaming) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startThread() {
|
||||||
|
Log.d(TAG, "started CurFPSThread")
|
||||||
|
mCurFPSThread = CurFPSThread(mView!!.handler)
|
||||||
|
surfaceFlingerFPS!!.start()
|
||||||
|
mCurFPSThread?.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopThread() {
|
||||||
|
if (mCurFPSThread != null && mCurFPSThread!!.isAlive) {
|
||||||
|
Log.d(TAG, "stopping CurFPSThread")
|
||||||
|
surfaceFlingerFPS!!.stop()
|
||||||
|
mCurFPSThread!!.interrupt()
|
||||||
|
try {
|
||||||
|
mCurFPSThread!!.join()
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCurFPSThread = null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var surfaceFlingerFPS: SurfaceFlingerFPS? = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Xiaomi-SM6250 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.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.service.quicksettings.Tile;
|
|
||||||
import android.service.quicksettings.TileService;
|
|
||||||
|
|
||||||
// TODO: Add FPS drawables
|
|
||||||
public class FPSTileService extends TileService {
|
|
||||||
|
|
||||||
private boolean isShowing = false;
|
|
||||||
|
|
||||||
public FPSTileService() { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStartListening() {
|
|
||||||
super.onStartListening();
|
|
||||||
ActivityManager manager =
|
|
||||||
(ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
|
||||||
for (ActivityManager.RunningServiceInfo service :
|
|
||||||
manager.getRunningServices(Integer.MAX_VALUE)) {
|
|
||||||
if (FPSInfoService.class.getName().equals(
|
|
||||||
service.service.getClassName())) {
|
|
||||||
isShowing = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateTile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick() {
|
|
||||||
Intent fpsinfo = new Intent(this, FPSInfoService.class);
|
|
||||||
if (!isShowing)
|
|
||||||
this.startService(fpsinfo);
|
|
||||||
else
|
|
||||||
this.stopService(fpsinfo);
|
|
||||||
isShowing = !isShowing;
|
|
||||||
updateTile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update tile
|
|
||||||
*/
|
|
||||||
private void updateTile() {
|
|
||||||
final Tile tile = getQsTile();
|
|
||||||
tile.setState(isShowing ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
|
||||||
tile.updateTile();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Xiaomi-SM6250 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.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
|
import android.content.Intent
|
||||||
|
import android.service.quicksettings.Tile
|
||||||
|
import android.service.quicksettings.TileService
|
||||||
|
|
||||||
|
// TODO: Add FPS drawables
|
||||||
|
class FPSTileService : TileService() {
|
||||||
|
private var isShowing = false
|
||||||
|
override fun onStartListening() {
|
||||||
|
super.onStartListening()
|
||||||
|
val manager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
|
||||||
|
for (service in manager.getRunningServices(Int.MAX_VALUE)) {
|
||||||
|
if (FPSInfoService::class.java.name ==
|
||||||
|
service.service.className
|
||||||
|
) {
|
||||||
|
isShowing = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateTile()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick() {
|
||||||
|
val fpsinfo = Intent(this, FPSInfoService::class.java)
|
||||||
|
if (!isShowing) startService(fpsinfo) else stopService(fpsinfo)
|
||||||
|
isShowing = !isShowing
|
||||||
|
updateTile()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTile() {
|
||||||
|
val tile = qsTile
|
||||||
|
tile.state =
|
||||||
|
if (isShowing) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
|
||||||
|
tile.updateTile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package com.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
public class GlobalConstants {
|
|
||||||
/**
|
|
||||||
* Global Variables
|
|
||||||
*/
|
|
||||||
public static final String FLASHLIGHT_SYSFS = "/sys/class/camera/flash/" +
|
|
||||||
"torch_brightness_lvl";
|
|
||||||
public static final String FLASHLIGHT_SYSFS_ENABLE = "/sys/class/camera/" +
|
|
||||||
"flash/torch_brightness_lvl_enable";
|
|
||||||
public static final String TMU_SYSFS = "/sys/devices/platform/11500000.mali/tmu";
|
|
||||||
public static final String TAG = "SamsungExtras";
|
|
||||||
public static final String FASTCHARGE_SYSFS = "/sys/class/sec/switch/afc_disable";
|
|
||||||
public static final String CHARGE_DISABLE_SYSFS = "/sys/devices/platform/battery/" +
|
|
||||||
"power_supply/battery/batt_slate_mode";
|
|
||||||
public static final String BATTERY_CAPACITY_MAX_SYSFS = "/sys/devices/platform/battery/"
|
|
||||||
+ "power_supply/battery/charge_full";
|
|
||||||
public static final String BATTERY_TEMP_SYSFS = "/sys/devices/platform/battery/"
|
|
||||||
+ "power_supply/battery/batt_temp";
|
|
||||||
public static final String BATTERY_CAPACITY_CURRENT_SYSFS = "/sys/devices/platform/battery/"
|
|
||||||
+ "power_supply/battery/capacity";
|
|
||||||
public static final String BATTERY_CURRENT_SYSFS = "/sys/devices/platform/battery/"
|
|
||||||
+ "power_supply/battery/current_now";
|
|
||||||
public static final String BATTERY_TIME_TO_FULL_SYSFS = "/sys/devices/platform/battery/"
|
|
||||||
+ "power_supply/battery/time_to_full_now";
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.eurekateam.samsungextras
|
||||||
|
|
||||||
|
object GlobalConstants {
|
||||||
|
/**
|
||||||
|
* Global Variables
|
||||||
|
*/
|
||||||
|
const val FLASHLIGHT_SYSFS = "/sys/class/camera/flash/" +
|
||||||
|
"torch_brightness_lvl"
|
||||||
|
const val TAG = "SamsungExtras"
|
||||||
|
}
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package com.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.service.quicksettings.TileService;
|
|
||||||
|
|
||||||
public class SamsungPartsTile extends TileService {
|
|
||||||
@Override
|
|
||||||
public void onClick() {
|
|
||||||
try {
|
|
||||||
Intent intent = new Intent(this, DeviceSettingsActivity.class);
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
startActivityAndCollapse(intent);
|
|
||||||
} catch (ActivityNotFoundException ignored) {
|
|
||||||
// At this point, the app is most likely hidden and set to only open from Settings
|
|
||||||
Intent intent = new Intent(this, DeviceSettings.class);
|
|
||||||
startActivityAndCollapse(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.service.quicksettings.TileService
|
||||||
|
|
||||||
|
class SamsungPartsTile : TileService() {
|
||||||
|
override fun onClick() {
|
||||||
|
try {
|
||||||
|
val intent = Intent(this, DeviceSettingsActivity::class.java)
|
||||||
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
startActivityAndCollapse(intent)
|
||||||
|
} catch (ignored: ActivityNotFoundException) {
|
||||||
|
// At this point, the app is most likely hidden and set to only open from Settings
|
||||||
|
val intent = Intent(this, DeviceSettings::class.java)
|
||||||
|
startActivityAndCollapse(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,25 +15,20 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.eurekateam.samsungextras;
|
package com.eurekateam.samsungextras
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context;
|
import android.content.Context
|
||||||
import android.content.Intent;
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences;
|
import androidx.preference.PreferenceManager
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
class Startup : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, bootintent: Intent) {
|
||||||
public class Startup extends BroadcastReceiver {
|
val enabled: Boolean
|
||||||
|
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
@Override
|
enabled = sharedPrefs.getBoolean(DeviceSettings.PREF_KEY_FPS_INFO, false)
|
||||||
public void onReceive(final Context context, final Intent bootintent) {
|
|
||||||
boolean enabled;
|
|
||||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
enabled = sharedPrefs.getBoolean(DeviceSettings.PREF_KEY_FPS_INFO, false);
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
context.startService(new Intent(context, FPSInfoService.class));
|
context.startService(Intent(context, FPSInfoService::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
package com.eurekateam.samsungextras;
|
|
||||||
|
|
||||||
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.ServiceManager;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2020-2021 Samsung Electronics Co. Ltd
|
|
||||||
* This Class is based on Samsung's OneUI 3.1
|
|
||||||
* /system/frameworks/gamesdk.jar
|
|
||||||
*/
|
|
||||||
public class SurfaceFlingerFPS {
|
|
||||||
private double mFps;
|
|
||||||
private final Object mLock;
|
|
||||||
private long mPrevFPSCheckStartTime;
|
|
||||||
private int mPrevFlipCount;
|
|
||||||
private double mPrevFps;
|
|
||||||
public boolean running;
|
|
||||||
private long mPrevPrevCheckStartTime;
|
|
||||||
private int mPrevPrevFlipCount;
|
|
||||||
private volatile boolean mSkipUpdate;
|
|
||||||
private volatile boolean mStopThread;
|
|
||||||
private ThreadGetFlip mThread;
|
|
||||||
|
|
||||||
private SurfaceFlingerFPS() {
|
|
||||||
this.mThread = null;
|
|
||||||
this.mStopThread = false;
|
|
||||||
this.mSkipUpdate = false;
|
|
||||||
this.mLock = new Object();
|
|
||||||
this.mFps = 0.0d;
|
|
||||||
this.mPrevFps = 0.0d;
|
|
||||||
this.mPrevFlipCount = 0;
|
|
||||||
this.mPrevFPSCheckStartTime = 0;
|
|
||||||
this.mPrevPrevFlipCount = 0;
|
|
||||||
this.mPrevPrevCheckStartTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the thread
|
|
||||||
*/
|
|
||||||
public void start() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (this.mThread == null || this.mStopThread) {
|
|
||||||
this.mStopThread = false;
|
|
||||||
ThreadGetFlip threadGetFlip = new ThreadGetFlip();
|
|
||||||
this.mThread = threadGetFlip;
|
|
||||||
threadGetFlip.start();
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the thread
|
|
||||||
*/
|
|
||||||
public void stop() {
|
|
||||||
synchronized (this) {
|
|
||||||
this.mStopThread = true;
|
|
||||||
if (this.mThread != null) {
|
|
||||||
this.mThread.interrupt();
|
|
||||||
}
|
|
||||||
this.mThread = null;
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the fps monitor is able to start
|
|
||||||
* @return true if able to start, else false
|
|
||||||
*/
|
|
||||||
private boolean isAvailable() {
|
|
||||||
return this.mStopThread || this.mThread == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCurrentFps() {
|
|
||||||
try {
|
|
||||||
synchronized (this.mLock) {
|
|
||||||
this.mSkipUpdate = true;
|
|
||||||
long curTime = System.currentTimeMillis();
|
|
||||||
int curFlipCount = getFlipCount();
|
|
||||||
if (curTime - this.mPrevFPSCheckStartTime < 200) {
|
|
||||||
this.mFps = ((double) (curFlipCount - this.mPrevPrevFlipCount)) / (((double) (curTime - this.mPrevPrevCheckStartTime)) / 1000.0d);
|
|
||||||
} else {
|
|
||||||
this.mFps = ((double) (curFlipCount - this.mPrevFlipCount)) / (((double) (curTime - this.mPrevFPSCheckStartTime)) / 1000.0d);
|
|
||||||
}
|
|
||||||
if (this.mFps < 1.0d) {
|
|
||||||
this.mFps = this.mPrevFps;
|
|
||||||
}
|
|
||||||
this.mPrevFlipCount = curFlipCount;
|
|
||||||
this.mPrevFPSCheckStartTime = curTime;
|
|
||||||
this.mPrevFps = this.mFps;
|
|
||||||
this.mSkipUpdate = false;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the fps value from internal thread
|
|
||||||
* @return fps value in Double
|
|
||||||
*/
|
|
||||||
public double getFps() {
|
|
||||||
if (isAvailable()) {
|
|
||||||
return -999.0d;
|
|
||||||
}
|
|
||||||
updateCurrentFps();
|
|
||||||
return this.mFps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the flip count from SurfaceFlinger Service
|
|
||||||
* @return flip count
|
|
||||||
*/
|
|
||||||
private int getFlipCount() {
|
|
||||||
int flipCount = -1;
|
|
||||||
try {
|
|
||||||
Parcel data = Parcel.obtain();
|
|
||||||
Parcel reply = Parcel.obtain();
|
|
||||||
try {
|
|
||||||
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
|
|
||||||
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
|
||||||
if (surfaceFlinger != null && surfaceFlinger.transact(1013, data, reply, 0)) {
|
|
||||||
flipCount = reply.readInt();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
data.recycle();
|
|
||||||
reply.recycle();
|
|
||||||
} catch (Exception e2) {
|
|
||||||
e2.printStackTrace();
|
|
||||||
}
|
|
||||||
return flipCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* access modifiers changed from: private */
|
|
||||||
|
|
||||||
public void updateFlipCountRecord() {
|
|
||||||
try {
|
|
||||||
synchronized (this.mLock) {
|
|
||||||
this.mPrevPrevCheckStartTime = this.mPrevFPSCheckStartTime;
|
|
||||||
this.mPrevPrevFlipCount = this.mPrevFlipCount;
|
|
||||||
this.mPrevFPSCheckStartTime = System.currentTimeMillis();
|
|
||||||
this.mPrevFlipCount = getFlipCount();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* access modifiers changed from: private */
|
|
||||||
/* loaded from: classes.dex */
|
|
||||||
public class ThreadGetFlip extends Thread {
|
|
||||||
private ThreadGetFlip() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // java.lang.Thread, java.lang.Runnable
|
|
||||||
public void run() {
|
|
||||||
while (!SurfaceFlingerFPS.this.mStopThread) {
|
|
||||||
if (!SurfaceFlingerFPS.this.mSkipUpdate) {
|
|
||||||
SurfaceFlingerFPS.this.updateFlipCountRecord();
|
|
||||||
try {
|
|
||||||
Thread.sleep(300);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of this class
|
|
||||||
* @return new instance
|
|
||||||
*/
|
|
||||||
public static SurfaceFlingerFPS getInstance(){
|
|
||||||
return new SurfaceFlingerFPS();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
package com.eurekateam.samsungextras
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.ServiceManager
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2021 Samsung Electronics Co. Ltd
|
||||||
|
* This Class is based on Samsung's OneUI 3.1
|
||||||
|
* /system/frameworks/gamesdk.jar
|
||||||
|
*/
|
||||||
|
class SurfaceFlingerFPS private constructor() {
|
||||||
|
private var mFps: Double
|
||||||
|
private val mLock: Any = Any()
|
||||||
|
private var mPrevFPSCheckStartTime: Long
|
||||||
|
private var mPrevFlipCount: Int
|
||||||
|
private var mPrevFps: Double
|
||||||
|
private var running = false
|
||||||
|
private var mPrevPrevCheckStartTime: Long
|
||||||
|
private var mPrevPrevFlipCount: Int
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var mSkipUpdate = false
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var mStopThread = false
|
||||||
|
private var mThread: ThreadGetFlip? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the thread
|
||||||
|
*/
|
||||||
|
fun start() {
|
||||||
|
synchronized(this) {
|
||||||
|
if (mThread == null || mStopThread) {
|
||||||
|
mStopThread = false
|
||||||
|
val threadGetFlip = ThreadGetFlip()
|
||||||
|
mThread = threadGetFlip
|
||||||
|
threadGetFlip.start()
|
||||||
|
running = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the thread
|
||||||
|
*/
|
||||||
|
fun stop() {
|
||||||
|
synchronized(this) {
|
||||||
|
mStopThread = true
|
||||||
|
if (mThread != null) {
|
||||||
|
mThread!!.interrupt()
|
||||||
|
}
|
||||||
|
mThread = null
|
||||||
|
running = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the fps monitor is able to start
|
||||||
|
* @return true if able to start, else false
|
||||||
|
*/
|
||||||
|
private val isAvailable: Boolean
|
||||||
|
get() = mStopThread || mThread == null
|
||||||
|
|
||||||
|
private fun updateCurrentFps() {
|
||||||
|
try {
|
||||||
|
synchronized(mLock) {
|
||||||
|
mSkipUpdate = true
|
||||||
|
val curTime = System.currentTimeMillis()
|
||||||
|
val curFlipCount = flipCount
|
||||||
|
mFps = if (curTime - mPrevFPSCheckStartTime < 200) {
|
||||||
|
(curFlipCount - mPrevPrevFlipCount).toDouble() / ((curTime - mPrevPrevCheckStartTime).toDouble() / 1000.0)
|
||||||
|
} else {
|
||||||
|
(curFlipCount - mPrevFlipCount).toDouble() / ((curTime - mPrevFPSCheckStartTime).toDouble() / 1000.0)
|
||||||
|
}
|
||||||
|
if (mFps < 1.0) {
|
||||||
|
mFps = mPrevFps
|
||||||
|
}
|
||||||
|
mPrevFlipCount = curFlipCount
|
||||||
|
mPrevFPSCheckStartTime = curTime
|
||||||
|
mPrevFps = mFps
|
||||||
|
mSkipUpdate = false
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the fps value from internal thread
|
||||||
|
* @return fps value in Double
|
||||||
|
*/
|
||||||
|
val fps: Double
|
||||||
|
get() {
|
||||||
|
if (isAvailable) {
|
||||||
|
return -999.0
|
||||||
|
}
|
||||||
|
updateCurrentFps()
|
||||||
|
return mFps
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the flip count from SurfaceFlinger Service
|
||||||
|
* @return flip count
|
||||||
|
*/
|
||||||
|
private val flipCount: Int
|
||||||
|
get() {
|
||||||
|
var flipCount = -1
|
||||||
|
try {
|
||||||
|
val data = Parcel.obtain()
|
||||||
|
val reply = Parcel.obtain()
|
||||||
|
try {
|
||||||
|
val surfaceFlinger = ServiceManager.getService("SurfaceFlinger")
|
||||||
|
data.writeInterfaceToken("android.ui.ISurfaceComposer")
|
||||||
|
if (surfaceFlinger != null && surfaceFlinger.transact(1013, data, reply, 0)) {
|
||||||
|
flipCount = reply.readInt()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
data.recycle()
|
||||||
|
reply.recycle()
|
||||||
|
} catch (e2: Exception) {
|
||||||
|
e2.printStackTrace()
|
||||||
|
}
|
||||||
|
return flipCount
|
||||||
|
}
|
||||||
|
|
||||||
|
/* access modifiers changed from: private */
|
||||||
|
fun updateFlipCountRecord() {
|
||||||
|
try {
|
||||||
|
synchronized(mLock) {
|
||||||
|
mPrevPrevCheckStartTime = mPrevFPSCheckStartTime
|
||||||
|
mPrevPrevFlipCount = mPrevFlipCount
|
||||||
|
mPrevFPSCheckStartTime = System.currentTimeMillis()
|
||||||
|
mPrevFlipCount = flipCount
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* access modifiers changed from: private */ /* loaded from: classes.dex */
|
||||||
|
inner class ThreadGetFlip : Thread() {
|
||||||
|
// java.lang.Thread, java.lang.Runnable
|
||||||
|
override fun run() {
|
||||||
|
while (!mStopThread) {
|
||||||
|
if (!mSkipUpdate) {
|
||||||
|
updateFlipCountRecord()
|
||||||
|
try {
|
||||||
|
sleep(300)
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Gets an instance of this class
|
||||||
|
* @return new instance
|
||||||
|
*/
|
||||||
|
val instance: SurfaceFlingerFPS
|
||||||
|
get() = SurfaceFlingerFPS()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
mFps = 0.0
|
||||||
|
mPrevFps = 0.0
|
||||||
|
mPrevFlipCount = 0
|
||||||
|
mPrevFPSCheckStartTime = 0
|
||||||
|
mPrevPrevFlipCount = 0
|
||||||
|
mPrevPrevCheckStartTime = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.battery;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
public class BatteryActivity extends FragmentActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
|
|
||||||
BatteryFragment batteryFragment;
|
|
||||||
if (fragment == null) {
|
|
||||||
batteryFragment = new BatteryFragment();
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.add(android.R.id.content, batteryFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.battery
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import com.android.internal.R.id.content
|
||||||
|
import com.android.internal.R.id.home
|
||||||
|
|
||||||
|
class BatteryActivity : FragmentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
|
val fragment = fragmentManager.findFragmentById(content)
|
||||||
|
val batteryFragment: BatteryFragment
|
||||||
|
if (fragment == null) {
|
||||||
|
batteryFragment = BatteryFragment()
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(content, batteryFragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == home) {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.battery;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.preference.ListPreference;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceFragment;
|
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.R;
|
|
||||||
import com.eurekateam.samsungextras.interfaces.Battery;
|
|
||||||
|
|
||||||
public class BatteryFragment extends PreferenceFragment implements
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
private static final String PREF_FASTCHARGE = "fastcharge_pref";
|
|
||||||
private static final String PREF_CHARGE = "charge_pref";
|
|
||||||
private static final String BATTERY_INFO = "battery_info";
|
|
||||||
private SwitchPreference mFastChargePref;
|
|
||||||
private SwitchPreference mChargePref;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
addPreferencesFromResource(R.xml.battery_settings);
|
|
||||||
mFastChargePref = findPreference(PREF_FASTCHARGE);
|
|
||||||
assert mFastChargePref != null;
|
|
||||||
mFastChargePref.setOnPreferenceChangeListener(this);
|
|
||||||
mFastChargePref.setChecked(Battery.getChargeSysfs() == 0);
|
|
||||||
mChargePref = findPreference(PREF_CHARGE);
|
|
||||||
assert mChargePref != null;
|
|
||||||
mChargePref.setOnPreferenceChangeListener(this);
|
|
||||||
mChargePref.setChecked(Battery.getFastChargeSysfs() == 0);
|
|
||||||
ListPreference mBatteryInfo = findPreference(BATTERY_INFO);
|
|
||||||
CharSequence[] items = {
|
|
||||||
Battery.getGeneralBatteryStats(1) + " mAh",
|
|
||||||
Battery.getGeneralBatteryStats(2) + " %",
|
|
||||||
Battery.getGeneralBatteryStats(3) + " mAh" ,
|
|
||||||
Battery.getGeneralBatteryStats(6) + " mAh",
|
|
||||||
Battery.getGeneralBatteryStats(4) == 1
|
|
||||||
? "Charging" : "Discharging",
|
|
||||||
Battery.getGeneralBatteryStats(5) + " \u2103",
|
|
||||||
};
|
|
||||||
assert mBatteryInfo != null;
|
|
||||||
mBatteryInfo.setEntryValues(items);
|
|
||||||
mBatteryInfo.setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
Toast.makeText(getContext(), (String) newValue, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
if (preference == mChargePref) {
|
|
||||||
Boolean value = (Boolean) newValue;
|
|
||||||
Battery.setChargeSysfs(value ? 0 : 1 );
|
|
||||||
mChargePref.setChecked(Battery.getChargeSysfs() == 0);
|
|
||||||
return true;
|
|
||||||
}else if (preference == mFastChargePref){
|
|
||||||
Boolean value = (Boolean) newValue;
|
|
||||||
Battery.setFastCharge(value ? 0 : 1 );
|
|
||||||
mFastChargePref.setChecked(Battery.getFastChargeSysfs() == 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.battery
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragment
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import com.eurekateam.samsungextras.R
|
||||||
|
import com.eurekateam.samsungextras.interfaces.Battery
|
||||||
|
|
||||||
|
class BatteryFragment : PreferenceFragment(), Preference.OnPreferenceChangeListener {
|
||||||
|
private var mFastChargePref: SwitchPreference? = null
|
||||||
|
private var mChargePref: SwitchPreference? = null
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
addPreferencesFromResource(R.xml.battery_settings)
|
||||||
|
mFastChargePref = findPreference(PREF_FASTCHARGE)
|
||||||
|
assert(mFastChargePref != null)
|
||||||
|
mFastChargePref!!.onPreferenceChangeListener = this
|
||||||
|
mFastChargePref!!.isChecked = Battery.chargeSysfs == 0
|
||||||
|
mChargePref = findPreference(PREF_CHARGE)
|
||||||
|
assert(mChargePref != null)
|
||||||
|
mChargePref!!.onPreferenceChangeListener = this
|
||||||
|
mChargePref!!.isChecked = Battery.fastChargeSysfs == 0
|
||||||
|
val mBatteryInfo = findPreference<ListPreference>(BATTERY_INFO)
|
||||||
|
val items = arrayOf<CharSequence>(
|
||||||
|
Battery.getGeneralBatteryStats(1).toString() + " mAh",
|
||||||
|
Battery.getGeneralBatteryStats(2).toString() + " %",
|
||||||
|
Battery.getGeneralBatteryStats(3).toString() + " mAh",
|
||||||
|
Battery.getGeneralBatteryStats(6).toString() + " mAh",
|
||||||
|
if (Battery.getGeneralBatteryStats(4) == 1) "Charging" else "Discharging",
|
||||||
|
Battery.getGeneralBatteryStats(5).toString() + " \u2103"
|
||||||
|
)
|
||||||
|
assert(mBatteryInfo != null)
|
||||||
|
mBatteryInfo!!.entryValues = items
|
||||||
|
mBatteryInfo.onPreferenceChangeListener =
|
||||||
|
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
|
||||||
|
Toast.makeText(
|
||||||
|
context, newValue as String?, Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
if (preference === mChargePref) {
|
||||||
|
val value = newValue as Boolean
|
||||||
|
Battery.chargeSysfs = if (value) 0 else 1
|
||||||
|
mChargePref!!.isChecked = Battery.chargeSysfs == 0
|
||||||
|
return true
|
||||||
|
} else if (preference === mFastChargePref) {
|
||||||
|
val value = newValue as Boolean
|
||||||
|
Battery.setFastCharge(if (value) 0 else 1)
|
||||||
|
mFastChargePref!!.isChecked =
|
||||||
|
Battery.fastChargeSysfs == 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val PREF_FASTCHARGE = "fastcharge_pref"
|
||||||
|
private const val PREF_CHARGE = "charge_pref"
|
||||||
|
private const val BATTERY_INFO = "battery_info"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.dolby;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
public class DolbyActivity extends FragmentActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
|
|
||||||
DolbyFragment dolbyFragment;
|
|
||||||
if (fragment == null) {
|
|
||||||
dolbyFragment = new DolbyFragment();
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.add(android.R.id.content, dolbyFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.dolby
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import com.android.internal.R.id.content
|
||||||
|
import com.android.internal.R.id.home
|
||||||
|
|
||||||
|
class DolbyActivity : FragmentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
|
val fragment = fragmentManager.findFragmentById(content)
|
||||||
|
val dolbyFragment: DolbyFragment
|
||||||
|
if (fragment == null) {
|
||||||
|
dolbyFragment = DolbyFragment()
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(content, dolbyFragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == home) {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,12 +4,14 @@ import android.media.audiofx.AudioEffect
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class DolbyCore {
|
class DolbyCore {
|
||||||
|
private var currentProfile : Int = -1
|
||||||
private val audioEffect = AudioEffect(
|
private val audioEffect = AudioEffect(
|
||||||
EFFECT_TYPE_DAP, AudioEffect.EFFECT_TYPE_NULL, 0, 0
|
EFFECT_TYPE_DAP, AudioEffect.EFFECT_TYPE_NULL, 0, 0
|
||||||
)
|
)
|
||||||
fun startDolbyEffect(PROFILE: Int){
|
fun startDolbyEffect(PROFILE: Int){
|
||||||
audioEffect.setParameter(EFFECT_PARAM_EFF_ENAB, 1)
|
audioEffect.setParameter(EFFECT_PARAM_EFF_ENAB, 1)
|
||||||
audioEffect.setParameter(EFFECT_PARAM_PROFILE, PROFILE)
|
audioEffect.setParameter(EFFECT_PARAM_PROFILE, PROFILE)
|
||||||
|
currentProfile = PROFILE
|
||||||
audioEffect.enabled = true
|
audioEffect.enabled = true
|
||||||
}
|
}
|
||||||
fun stopDolbyEffect(){
|
fun stopDolbyEffect(){
|
||||||
|
|
@ -22,6 +24,9 @@ class DolbyCore {
|
||||||
audioEffect.enabled = true
|
audioEffect.enabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun currentState(): Int{
|
||||||
|
return currentProfile
|
||||||
|
}
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val EFFECT_TYPE_DAP = UUID.fromString("46d279d9-9be7-453d-9d7c-ef937f675587")
|
private val EFFECT_TYPE_DAP = UUID.fromString("46d279d9-9be7-453d-9d7c-ef937f675587")
|
||||||
|
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.dolby;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.preference.ListPreference;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceFragment;
|
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.R;
|
|
||||||
|
|
||||||
public class DolbyFragment extends PreferenceFragment implements
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
private static final String PREF_DOLBY = "dolby_pref";
|
|
||||||
private static final String DOLBY_MODES = "dolby_modes";
|
|
||||||
ListPreference DolbyModesPreference;
|
|
||||||
SwitchPreference DolbyEnablePreference;
|
|
||||||
DolbyCore dolbyCore = new DolbyCore();
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
addPreferencesFromResource(R.xml.dolby_settings);
|
|
||||||
DolbyModesPreference = findPreference(DOLBY_MODES);
|
|
||||||
DolbyEnablePreference = findPreference(PREF_DOLBY);
|
|
||||||
assert DolbyEnablePreference != null;
|
|
||||||
DolbyEnablePreference.setChecked(dolbyCore.isRunning());
|
|
||||||
DolbyEnablePreference.setOnPreferenceChangeListener(this);
|
|
||||||
CharSequence[] items = {
|
|
||||||
"1", "2", "3", "4", "5", "6", "7", "8", "9"
|
|
||||||
};
|
|
||||||
DolbyModesPreference.setEntryValues(items);
|
|
||||||
DolbyModesPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
switch (Integer.parseInt((String) newValue)){
|
|
||||||
case 1:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_AUTO);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_GAME);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_GAME_1);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_GAME_2);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_MOVIE);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_MUSIC);
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_OFF);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_VOICE);
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
dolbyCore.startDolbyEffect(DolbyCore.PROFILE_SPACIAL_AUDIO);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
if (preference == DolbyEnablePreference) {
|
|
||||||
Boolean value = (Boolean) newValue;
|
|
||||||
if(value){
|
|
||||||
dolbyCore.justStartOnly();
|
|
||||||
}else{
|
|
||||||
dolbyCore.stopDolbyEffect();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.dolby
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragment
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import com.eurekateam.samsungextras.R
|
||||||
|
|
||||||
|
class DolbyFragment : PreferenceFragment(), Preference.OnPreferenceChangeListener {
|
||||||
|
private var DolbyModesPreference: ListPreference? = null
|
||||||
|
private var DolbyEnablePreference: SwitchPreference? = null
|
||||||
|
private var dolbyCore = DolbyCore()
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
addPreferencesFromResource(R.xml.dolby_settings)
|
||||||
|
DolbyModesPreference = findPreference(DOLBY_MODES)
|
||||||
|
DolbyEnablePreference = findPreference(PREF_DOLBY)
|
||||||
|
assert(DolbyEnablePreference != null)
|
||||||
|
DolbyEnablePreference!!.isChecked = dolbyCore.isRunning()
|
||||||
|
DolbyEnablePreference!!.onPreferenceChangeListener = this
|
||||||
|
val items = arrayOf<CharSequence>(
|
||||||
|
"1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||||
|
)
|
||||||
|
DolbyModesPreference!!.entryValues = items
|
||||||
|
DolbyModesPreference!!.onPreferenceChangeListener =
|
||||||
|
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||||
|
when ((newValue as String?)?.toInt()) {
|
||||||
|
1 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_AUTO)
|
||||||
|
2 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_GAME)
|
||||||
|
3 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_GAME_1)
|
||||||
|
4 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_GAME_2)
|
||||||
|
5 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_MOVIE)
|
||||||
|
6 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_MUSIC)
|
||||||
|
7 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_OFF)
|
||||||
|
8 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_VOICE)
|
||||||
|
9 -> dolbyCore.startDolbyEffect(DolbyCore.PROFILE_SPACIAL_AUDIO)
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
if (preference === DolbyEnablePreference) {
|
||||||
|
val value = newValue as Boolean
|
||||||
|
if (value) {
|
||||||
|
dolbyCore.justStartOnly()
|
||||||
|
} else {
|
||||||
|
dolbyCore.stopDolbyEffect()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val PREF_DOLBY = "dolby_pref"
|
||||||
|
private const val DOLBY_MODES = "dolby_modes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.flashlight;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
public class FlashLightActivity extends FragmentActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
|
|
||||||
FlashLightFragment flashLightFragment;
|
|
||||||
if (fragment == null) {
|
|
||||||
flashLightFragment = new FlashLightFragment();
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.add(android.R.id.content, flashLightFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.flashlight
|
||||||
|
|
||||||
|
import android.R.id.content
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import com.android.internal.R.id.home
|
||||||
|
|
||||||
|
class FlashLightActivity : FragmentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
|
val fragment = fragmentManager.findFragmentById(content)
|
||||||
|
val flashLightFragment: FlashLightFragment
|
||||||
|
if (fragment == null) {
|
||||||
|
flashLightFragment = FlashLightFragment()
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(content, flashLightFragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == home) {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.flashlight;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceFragment;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.GlobalConstants;
|
|
||||||
import com.eurekateam.samsungextras.R;
|
|
||||||
import com.eurekateam.samsungextras.interfaces.Flashlight;
|
|
||||||
import com.eurekateam.samsungextras.preferences.CustomSeekBarPreference;
|
|
||||||
import com.eurekateam.samsungextras.utils.FileUtilsWrapper;
|
|
||||||
import com.eurekateam.samsungextras.utils.SystemProperties;
|
|
||||||
|
|
||||||
public class FlashLightFragment extends PreferenceFragment implements
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
private static final String PREF_FLASHLIGHT = "flashlight_pref";
|
|
||||||
private CustomSeekBarPreference mFlashLightPref;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
addPreferencesFromResource(R.xml.flashlight_settings);
|
|
||||||
mFlashLightPref = findPreference(PREF_FLASHLIGHT);
|
|
||||||
assert mFlashLightPref != null;
|
|
||||||
mFlashLightPref.setOnPreferenceChangeListener(this);
|
|
||||||
if (!FileUtilsWrapper.fileExists(GlobalConstants.FLASHLIGHT_SYSFS)){
|
|
||||||
mFlashLightPref.setEnabled(false);
|
|
||||||
}
|
|
||||||
mFlashLightPref.setMax(10);
|
|
||||||
mFlashLightPref.setMin(1);
|
|
||||||
boolean isa10 = SystemProperties.read("ro.product.device").equals("a10");
|
|
||||||
mFlashLightPref.setValue(Flashlight.getFlash(isa10 ? 1 : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
if (preference == mFlashLightPref) {
|
|
||||||
Integer value = (Integer) newValue;
|
|
||||||
Flashlight.setFlash(value);
|
|
||||||
mFlashLightPref.setValue(value, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.flashlight
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragment
|
||||||
|
import com.eurekateam.samsungextras.GlobalConstants
|
||||||
|
import com.eurekateam.samsungextras.R
|
||||||
|
import com.eurekateam.samsungextras.interfaces.Flashlight
|
||||||
|
import com.eurekateam.samsungextras.preferences.CustomSeekBarPreference
|
||||||
|
import com.eurekateam.samsungextras.utils.SystemProperties
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class FlashLightFragment : PreferenceFragment(), Preference.OnPreferenceChangeListener {
|
||||||
|
private var mFlashLightPref: CustomSeekBarPreference? = null
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
addPreferencesFromResource(R.xml.flashlight_settings)
|
||||||
|
mFlashLightPref = findPreference(PREF_FLASHLIGHT)
|
||||||
|
assert(mFlashLightPref != null)
|
||||||
|
mFlashLightPref!!.onPreferenceChangeListener = this
|
||||||
|
if (!File(GlobalConstants.FLASHLIGHT_SYSFS).exists()) {
|
||||||
|
mFlashLightPref!!.isEnabled = false
|
||||||
|
}
|
||||||
|
mFlashLightPref!!.setMax(10)
|
||||||
|
mFlashLightPref!!.setMin(1)
|
||||||
|
val isa10 = SystemProperties.read("ro.product.device") == "a10"
|
||||||
|
mFlashLightPref!!.value = Flashlight.getFlash(if (isa10) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
if (preference === mFlashLightPref) {
|
||||||
|
val value = newValue as Int
|
||||||
|
Flashlight.setFlash(value)
|
||||||
|
mFlashLightPref!!.setValue(value, true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val PREF_FLASHLIGHT = "flashlight_pref"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.interfaces;
|
|
||||||
|
|
||||||
public class Battery {
|
|
||||||
public static native void setChargeSysfs(int enable);
|
|
||||||
public static native int getChargeSysfs();
|
|
||||||
public static native void setFastCharge(int enable);
|
|
||||||
public static native int getFastChargeSysfs();
|
|
||||||
public static native int getGeneralBatteryStats(int id);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.eurekateam.samsungextras.interfaces
|
||||||
|
|
||||||
|
object Battery {
|
||||||
|
var chargeSysfs: Int
|
||||||
|
external get
|
||||||
|
external set
|
||||||
|
|
||||||
|
external fun setFastCharge(enable: Int)
|
||||||
|
val fastChargeSysfs: Int
|
||||||
|
external get
|
||||||
|
|
||||||
|
external fun getGeneralBatteryStats(id: Int): Int
|
||||||
|
}
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.interfaces;
|
|
||||||
|
|
||||||
public class Flashlight {
|
|
||||||
public static native void setFlash(int value);
|
|
||||||
public static native int getFlash(int isA10);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.eurekateam.samsungextras.interfaces
|
||||||
|
|
||||||
|
object Flashlight {
|
||||||
|
external fun setFlash(value: Int)
|
||||||
|
external fun getFlash(isA10: Int): Int
|
||||||
|
}
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.interfaces;
|
|
||||||
|
|
||||||
public class GPU {
|
|
||||||
public static native void setGPU(int enable);
|
|
||||||
public static native int getGPU();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.eurekateam.samsungextras.interfaces
|
||||||
|
|
||||||
|
object GPU {
|
||||||
|
var GPU: Int
|
||||||
|
external get
|
||||||
|
external set
|
||||||
|
}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.interfaces;
|
|
||||||
|
|
||||||
public class SELinux {
|
|
||||||
public static native int getSELinux();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.eurekateam.samsungextras.interfaces
|
||||||
|
|
||||||
|
object SELinux {
|
||||||
|
val SELinux: Int
|
||||||
|
external get
|
||||||
|
}
|
||||||
|
|
@ -1,328 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.preferences;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import androidx.core.content.res.TypedArrayUtils;
|
|
||||||
import androidx.preference.*;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.ViewParent;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.R;
|
|
||||||
|
|
||||||
public class CustomSeekBarPreference extends Preference implements SeekBar.OnSeekBarChangeListener,
|
|
||||||
View.OnClickListener, View.OnLongClickListener {
|
|
||||||
protected final String TAG = getClass().getName();
|
|
||||||
private static final String APP_NS = "http://schemas.android.com/apk/res-auto";
|
|
||||||
protected static final String ANDROIDNS = "http://schemas.android.com/apk/res/android";
|
|
||||||
|
|
||||||
protected int mInterval = 1;
|
|
||||||
protected boolean mShowSign = false;
|
|
||||||
protected String mUnits = "";
|
|
||||||
protected boolean mContinuousUpdates = false;
|
|
||||||
|
|
||||||
protected int mMinValue = 1;
|
|
||||||
protected int mMaxValue = 256;
|
|
||||||
protected boolean mDefaultValueExists = false;
|
|
||||||
protected int mDefaultValue;
|
|
||||||
|
|
||||||
protected int mValue;
|
|
||||||
|
|
||||||
protected TextView mValueTextView;
|
|
||||||
protected ImageView mResetImageView;
|
|
||||||
protected ImageView mMinusImageView;
|
|
||||||
protected ImageView mPlusImageView;
|
|
||||||
protected SeekBar mSeekBar;
|
|
||||||
|
|
||||||
protected boolean mTrackingTouch = false;
|
|
||||||
protected int mTrackingValue;
|
|
||||||
|
|
||||||
public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
|
||||||
|
|
||||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomSeekBarPreference);
|
|
||||||
try {
|
|
||||||
mShowSign = a.getBoolean(R.styleable.CustomSeekBarPreference_showSign, mShowSign);
|
|
||||||
String units = a.getString(R.styleable.CustomSeekBarPreference_units);
|
|
||||||
if (units != null)
|
|
||||||
mUnits = " " + units;
|
|
||||||
mContinuousUpdates = a.getBoolean(R.styleable.CustomSeekBarPreference_continuousUpdates, mContinuousUpdates);
|
|
||||||
} finally {
|
|
||||||
a.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
String newInterval = attrs.getAttributeValue(APP_NS, "interval");
|
|
||||||
if (newInterval != null)
|
|
||||||
mInterval = Integer.parseInt(newInterval);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Invalid interval value", e);
|
|
||||||
}
|
|
||||||
mMinValue = attrs.getAttributeIntValue(APP_NS, "min", mMinValue);
|
|
||||||
mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", mMaxValue);
|
|
||||||
if (mMaxValue < mMinValue)
|
|
||||||
mMaxValue = mMinValue;
|
|
||||||
String defaultValue = attrs.getAttributeValue(ANDROIDNS, "defaultValue");
|
|
||||||
mDefaultValueExists = defaultValue != null && !defaultValue.isEmpty();
|
|
||||||
if (mDefaultValueExists) {
|
|
||||||
mDefaultValue = getLimitedValue(Integer.parseInt(defaultValue));
|
|
||||||
mValue = mDefaultValue;
|
|
||||||
} else {
|
|
||||||
mValue = mMinValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSeekBar = new SeekBar(context, attrs);
|
|
||||||
setLayoutResource(R.layout.preference_custom_seekbar);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
this(context, attrs, defStyleAttr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomSeekBarPreference(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, TypedArrayUtils.getAttr(context,
|
|
||||||
androidx.preference.R.attr.preferenceStyle,
|
|
||||||
android.R.attr.preferenceStyle));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomSeekBarPreference(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
|
||||||
super.onBindViewHolder(holder);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// move our seekbar to the new view we've been given
|
|
||||||
ViewParent oldContainer = mSeekBar.getParent();
|
|
||||||
ViewGroup newContainer = (ViewGroup) holder.findViewById(R.id.seekbar);
|
|
||||||
if (oldContainer != newContainer) {
|
|
||||||
// remove the seekbar from the old view
|
|
||||||
if (oldContainer != null) {
|
|
||||||
((ViewGroup) oldContainer).removeView(mSeekBar);
|
|
||||||
}
|
|
||||||
// remove the existing seekbar (there may not be one) and add ours
|
|
||||||
newContainer.removeAllViews();
|
|
||||||
newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Log.e(TAG, "Error binding view: " + ex.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
mSeekBar.setMax(getSeekValue(mMaxValue));
|
|
||||||
mSeekBar.setProgress(getSeekValue(mValue));
|
|
||||||
mSeekBar.setEnabled(isEnabled());
|
|
||||||
|
|
||||||
mValueTextView = (TextView) holder.findViewById(R.id.value);
|
|
||||||
mResetImageView = (ImageView) holder.findViewById(R.id.reset);
|
|
||||||
mMinusImageView = (ImageView) holder.findViewById(R.id.minus);
|
|
||||||
mPlusImageView = (ImageView) holder.findViewById(R.id.plus);
|
|
||||||
|
|
||||||
updateValueViews();
|
|
||||||
|
|
||||||
mSeekBar.setOnSeekBarChangeListener(this);
|
|
||||||
mResetImageView.setOnClickListener(this);
|
|
||||||
mMinusImageView.setOnClickListener(this);
|
|
||||||
mPlusImageView.setOnClickListener(this);
|
|
||||||
mResetImageView.setOnLongClickListener(this);
|
|
||||||
mMinusImageView.setOnLongClickListener(this);
|
|
||||||
mPlusImageView.setOnLongClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getLimitedValue(int v) {
|
|
||||||
return v < mMinValue ? mMinValue : (v > mMaxValue ? mMaxValue : v);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getSeekValue(int v) {
|
|
||||||
return 0 - Math.floorDiv(mMinValue - v, mInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getTextValue(int v) {
|
|
||||||
return (mShowSign && v > 0 ? "+" : "") + String.valueOf(v) + mUnits;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateValueViews() {
|
|
||||||
if (mValueTextView != null) {
|
|
||||||
mValueTextView.setText(getContext().getString(R.string.custom_seekbar_value,
|
|
||||||
(!mTrackingTouch || mContinuousUpdates ? getTextValue(mValue) +
|
|
||||||
(mDefaultValueExists && mValue == mDefaultValue ? " (" +
|
|
||||||
getContext().getString(R.string.custom_seekbar_default_value) + ")" : "")
|
|
||||||
: getTextValue(mTrackingValue))));
|
|
||||||
}
|
|
||||||
if (mResetImageView != null) {
|
|
||||||
if (!mDefaultValueExists || mValue == mDefaultValue || mTrackingTouch)
|
|
||||||
mResetImageView.setVisibility(View.INVISIBLE);
|
|
||||||
else
|
|
||||||
mResetImageView.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
if (mMinusImageView != null) {
|
|
||||||
if (mValue == mMinValue || mTrackingTouch) {
|
|
||||||
mMinusImageView.setClickable(false);
|
|
||||||
mMinusImageView.setColorFilter(getContext().getColor(R.color.disabled_text_color),
|
|
||||||
PorterDuff.Mode.MULTIPLY);
|
|
||||||
} else {
|
|
||||||
mMinusImageView.setClickable(true);
|
|
||||||
mMinusImageView.clearColorFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mPlusImageView != null) {
|
|
||||||
if (mValue == mMaxValue || mTrackingTouch) {
|
|
||||||
mPlusImageView.setClickable(false);
|
|
||||||
mPlusImageView.setColorFilter(getContext().getColor(R.color.disabled_text_color), PorterDuff.Mode.MULTIPLY);
|
|
||||||
} else {
|
|
||||||
mPlusImageView.setClickable(true);
|
|
||||||
mPlusImageView.clearColorFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void changeValue(int newValue) {
|
|
||||||
// for subclasses
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
|
||||||
int newValue = getLimitedValue(mMinValue + (progress * mInterval));
|
|
||||||
if (mTrackingTouch && !mContinuousUpdates) {
|
|
||||||
mTrackingValue = newValue;
|
|
||||||
updateValueViews();
|
|
||||||
} else if (mValue != newValue) {
|
|
||||||
// change rejected, revert to the previous value
|
|
||||||
if (!callChangeListener(newValue)) {
|
|
||||||
mSeekBar.setProgress(getSeekValue(mValue));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// change accepted, store it
|
|
||||||
changeValue(newValue);
|
|
||||||
persistInt(newValue);
|
|
||||||
|
|
||||||
mValue = newValue;
|
|
||||||
updateValueViews();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
|
||||||
mTrackingValue = mValue;
|
|
||||||
mTrackingTouch = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
|
||||||
mTrackingTouch = false;
|
|
||||||
if (!mContinuousUpdates)
|
|
||||||
onProgressChanged(mSeekBar, getSeekValue(mTrackingValue), false);
|
|
||||||
notifyChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
int id = v.getId();
|
|
||||||
if (id == R.id.reset) {
|
|
||||||
Toast.makeText(getContext(), getContext().getString(R.string.custom_seekbar_default_value_to_set, getTextValue(mDefaultValue)),
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
} else if (id == R.id.minus) {
|
|
||||||
setValue(mValue - mInterval, true);
|
|
||||||
} else if (id == R.id.plus) {
|
|
||||||
setValue(mValue + mInterval, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v) {
|
|
||||||
int id = v.getId();
|
|
||||||
if (id == R.id.reset) {
|
|
||||||
setValue(mDefaultValue, true);
|
|
||||||
//Toast.makeText(getContext(), getContext().getString(R.string.custom_seekbar_default_value_is_set),
|
|
||||||
// Toast.LENGTH_LONG).show();
|
|
||||||
} else if (id == R.id.minus) {
|
|
||||||
setValue(mMaxValue - mMinValue > mInterval * 2 && mMaxValue + mMinValue < mValue * 2 ? Math.floorDiv(mMaxValue + mMinValue, 2) : mMinValue, true);
|
|
||||||
} else if (id == R.id.plus) {
|
|
||||||
setValue(mMaxValue - mMinValue > mInterval * 2 && mMaxValue + mMinValue > mValue * 2 ? -1 * Math.floorDiv(-1 * (mMaxValue + mMinValue), 2) : mMaxValue, true);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dont need too much shit about initial and default values
|
|
||||||
// its all done in constructor already
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
|
||||||
if (restoreValue)
|
|
||||||
mValue = getPersistedInt(mValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDefaultValue(Object defaultValue) {
|
|
||||||
if (defaultValue instanceof Integer)
|
|
||||||
setDefaultValue((Integer) defaultValue, mSeekBar != null);
|
|
||||||
else
|
|
||||||
setDefaultValue(defaultValue == null ? (String) null : defaultValue.toString(), mSeekBar != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultValue(int newValue, boolean update) {
|
|
||||||
newValue = getLimitedValue(newValue);
|
|
||||||
if (!mDefaultValueExists || mDefaultValue != newValue) {
|
|
||||||
mDefaultValueExists = true;
|
|
||||||
mDefaultValue = newValue;
|
|
||||||
if (update)
|
|
||||||
updateValueViews();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultValue(String newValue, boolean update) {
|
|
||||||
if (mDefaultValueExists && (newValue == null || newValue.isEmpty())) {
|
|
||||||
mDefaultValueExists = false;
|
|
||||||
if (update)
|
|
||||||
updateValueViews();
|
|
||||||
} else if (newValue != null && !newValue.isEmpty()) {
|
|
||||||
setDefaultValue(Integer.parseInt(newValue), update);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMax(int max) {
|
|
||||||
mMaxValue = max;
|
|
||||||
mSeekBar.setMax(mMaxValue - mMinValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMin(int min) {
|
|
||||||
mMinValue = min;
|
|
||||||
mSeekBar.setMax(mMaxValue - mMinValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(int newValue) {
|
|
||||||
mValue = getLimitedValue(newValue);
|
|
||||||
if (mSeekBar != null) mSeekBar.setProgress(getSeekValue(mValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(int newValue, boolean update) {
|
|
||||||
newValue = getLimitedValue(newValue);
|
|
||||||
if (mValue != newValue) {
|
|
||||||
if (update)
|
|
||||||
mSeekBar.setProgress(getSeekValue(newValue));
|
|
||||||
else
|
|
||||||
mValue = newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValue() {
|
|
||||||
return mValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need some methods here to set/get other attrs at runtime,
|
|
||||||
// but who really need this ...
|
|
||||||
|
|
||||||
public void refresh(int newValue) {
|
|
||||||
// this will ...
|
|
||||||
setValue(newValue, mSeekBar != null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,323 @@
|
||||||
|
package com.eurekateam.samsungextras.preferences
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.OnLongClickListener
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import android.widget.SeekBar.OnSeekBarChangeListener
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.res.TypedArrayUtils
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceViewHolder
|
||||||
|
import androidx.preference.R
|
||||||
|
|
||||||
|
open class CustomSeekBarPreference @JvmOverloads constructor(
|
||||||
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = TypedArrayUtils.getAttr(
|
||||||
|
context,
|
||||||
|
R.attr.preferenceStyle,
|
||||||
|
android.R.attr.preferenceStyle
|
||||||
|
), defStyleRes: Int = 0
|
||||||
|
) : Preference(context, attrs, defStyleAttr, defStyleRes), OnSeekBarChangeListener,
|
||||||
|
View.OnClickListener, OnLongClickListener {
|
||||||
|
private val TAG: String = javaClass.name
|
||||||
|
private var mInterval = 1
|
||||||
|
private var mShowSign = false
|
||||||
|
private var mUnits = ""
|
||||||
|
private var mContinuousUpdates = false
|
||||||
|
private var mMinValue = 1
|
||||||
|
private var mMaxValue = 256
|
||||||
|
private var mDefaultValueExists: Boolean
|
||||||
|
private var mDefaultValue = 0
|
||||||
|
private var mValue = 0
|
||||||
|
private var mValueTextView: TextView? = null
|
||||||
|
private var mResetImageView: ImageView? = null
|
||||||
|
private var mMinusImageView: ImageView? = null
|
||||||
|
private var mPlusImageView: ImageView? = null
|
||||||
|
private var mSeekBar: SeekBar
|
||||||
|
private var mTrackingTouch = false
|
||||||
|
private var mTrackingValue = 0
|
||||||
|
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||||
|
super.onBindViewHolder(holder)
|
||||||
|
try {
|
||||||
|
// move our seekbar to the new view we've been given
|
||||||
|
val oldContainer = mSeekBar.parent
|
||||||
|
val newContainer =
|
||||||
|
holder.findViewById(com.eurekateam.samsungextras.R.id.seekbar) as ViewGroup
|
||||||
|
if (oldContainer !== newContainer) {
|
||||||
|
// remove the seekbar from the old view
|
||||||
|
if (oldContainer != null) {
|
||||||
|
(oldContainer as ViewGroup).removeView(mSeekBar)
|
||||||
|
}
|
||||||
|
// remove the existing seekbar (there may not be one) and add ours
|
||||||
|
newContainer.removeAllViews()
|
||||||
|
newContainer.addView(
|
||||||
|
mSeekBar, ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Log.e(TAG, "Error binding view: $ex")
|
||||||
|
}
|
||||||
|
mSeekBar.max = getSeekValue(mMaxValue)
|
||||||
|
mSeekBar.progress = getSeekValue(mValue)
|
||||||
|
mSeekBar.isEnabled = isEnabled
|
||||||
|
mValueTextView = holder.findViewById(com.eurekateam.samsungextras.R.id.value) as TextView
|
||||||
|
mResetImageView = holder.findViewById(com.eurekateam.samsungextras.R.id.reset) as ImageView
|
||||||
|
mMinusImageView = holder.findViewById(com.eurekateam.samsungextras.R.id.minus) as ImageView
|
||||||
|
mPlusImageView = holder.findViewById(com.eurekateam.samsungextras.R.id.plus) as ImageView
|
||||||
|
updateValueViews()
|
||||||
|
mSeekBar.setOnSeekBarChangeListener(this)
|
||||||
|
mResetImageView!!.setOnClickListener(this)
|
||||||
|
mMinusImageView!!.setOnClickListener(this)
|
||||||
|
mPlusImageView!!.setOnClickListener(this)
|
||||||
|
mResetImageView!!.onLongClickListener = this
|
||||||
|
mMinusImageView!!.onLongClickListener = this
|
||||||
|
mPlusImageView!!.onLongClickListener = this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLimitedValue(v: Int): Int {
|
||||||
|
return if (v < mMinValue) mMinValue else v.coerceAtMost(mMaxValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSeekValue(v: Int): Int {
|
||||||
|
return -Math.floorDiv(mMinValue - v, mInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTextValue(v: Int): String {
|
||||||
|
return (if (mShowSign && v > 0) "+" else "") + v + mUnits
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateValueViews() {
|
||||||
|
if (mValueTextView != null) {
|
||||||
|
mValueTextView!!.text = context.getString(
|
||||||
|
com.eurekateam.samsungextras.R.string.custom_seekbar_value,
|
||||||
|
if (!mTrackingTouch || mContinuousUpdates) getTextValue(mValue) +
|
||||||
|
(if (mDefaultValueExists && mValue == mDefaultValue) " (" +
|
||||||
|
context.getString(com.eurekateam.samsungextras.R.string.custom_seekbar_default_value) + ")" else "") else getTextValue(
|
||||||
|
mTrackingValue
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mResetImageView != null) {
|
||||||
|
if (!mDefaultValueExists || mValue == mDefaultValue || mTrackingTouch) mResetImageView!!.visibility =
|
||||||
|
View.INVISIBLE else mResetImageView!!.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
if (mMinusImageView != null) {
|
||||||
|
if (mValue == mMinValue || mTrackingTouch) {
|
||||||
|
mMinusImageView!!.isClickable = false
|
||||||
|
mMinusImageView!!.setColorFilter(
|
||||||
|
context.getColor(com.eurekateam.samsungextras.R.color.disabled_text_color),
|
||||||
|
PorterDuff.Mode.MULTIPLY
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
mMinusImageView!!.isClickable = true
|
||||||
|
mMinusImageView!!.clearColorFilter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mPlusImageView != null) {
|
||||||
|
if (mValue == mMaxValue || mTrackingTouch) {
|
||||||
|
mPlusImageView!!.isClickable = false
|
||||||
|
mPlusImageView!!.setColorFilter(
|
||||||
|
context.getColor(com.eurekateam.samsungextras.R.color.disabled_text_color),
|
||||||
|
PorterDuff.Mode.MULTIPLY
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
mPlusImageView!!.isClickable = true
|
||||||
|
mPlusImageView!!.clearColorFilter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun changeValue() {
|
||||||
|
// for subclasses
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
|
val newValue = getLimitedValue(mMinValue + progress * mInterval)
|
||||||
|
if (mTrackingTouch && !mContinuousUpdates) {
|
||||||
|
mTrackingValue = newValue
|
||||||
|
updateValueViews()
|
||||||
|
} else if (mValue != newValue) {
|
||||||
|
// change rejected, revert to the previous value
|
||||||
|
if (!callChangeListener(newValue)) {
|
||||||
|
mSeekBar.progress = getSeekValue(mValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// change accepted, store it
|
||||||
|
changeValue()
|
||||||
|
persistInt(newValue)
|
||||||
|
mValue = newValue
|
||||||
|
updateValueViews()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||||
|
mTrackingValue = mValue
|
||||||
|
mTrackingTouch = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||||
|
mTrackingTouch = false
|
||||||
|
if (!mContinuousUpdates) onProgressChanged(mSeekBar, getSeekValue(mTrackingValue), false)
|
||||||
|
notifyChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
when (v.id) {
|
||||||
|
com.eurekateam.samsungextras.R.id.reset -> {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.getString(
|
||||||
|
com.eurekateam.samsungextras.R.string.custom_seekbar_default_value_to_set,
|
||||||
|
getTextValue(mDefaultValue)
|
||||||
|
),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
com.eurekateam.samsungextras.R.id.minus -> {
|
||||||
|
setValue(mValue - mInterval, true)
|
||||||
|
}
|
||||||
|
com.eurekateam.samsungextras.R.id.plus -> {
|
||||||
|
setValue(mValue + mInterval, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(v: View): Boolean {
|
||||||
|
when (v.id) {
|
||||||
|
com.eurekateam.samsungextras.R.id.reset -> {
|
||||||
|
setValue(mDefaultValue, true)
|
||||||
|
}
|
||||||
|
com.eurekateam.samsungextras.R.id.minus -> {
|
||||||
|
setValue(
|
||||||
|
if (mMaxValue - mMinValue > mInterval * 2 && mMaxValue + mMinValue < mValue * 2) Math.floorDiv(
|
||||||
|
mMaxValue + mMinValue,
|
||||||
|
2
|
||||||
|
) else mMinValue, true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
com.eurekateam.samsungextras.R.id.plus -> {
|
||||||
|
setValue(
|
||||||
|
if (mMaxValue - mMinValue > mInterval * 2 && mMaxValue + mMinValue > mValue * 2) -1 * Math.floorDiv(
|
||||||
|
-1 * (mMaxValue + mMinValue),
|
||||||
|
2
|
||||||
|
) else mMaxValue, true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// dont need too much shit about initial and default values
|
||||||
|
// its all done in constructor already
|
||||||
|
override fun onSetInitialValue(restoreValue: Boolean, defaultValue: Any) {
|
||||||
|
if (restoreValue) mValue = getPersistedInt(mValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setDefaultValue(defaultValue: Any) {
|
||||||
|
if (defaultValue is Int) setDefaultValue(
|
||||||
|
defaultValue,
|
||||||
|
true
|
||||||
|
) else setDefaultValue(
|
||||||
|
defaultValue.toString(), true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setDefaultValue(newValue: Int, update: Boolean) {
|
||||||
|
var newValue = newValue
|
||||||
|
newValue = getLimitedValue(newValue)
|
||||||
|
if (!mDefaultValueExists || mDefaultValue != newValue) {
|
||||||
|
mDefaultValueExists = true
|
||||||
|
mDefaultValue = newValue
|
||||||
|
if (update) updateValueViews()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setDefaultValue(newValue: String?, update: Boolean) {
|
||||||
|
if (mDefaultValueExists && (newValue == null || newValue.isEmpty())) {
|
||||||
|
mDefaultValueExists = false
|
||||||
|
if (update) updateValueViews()
|
||||||
|
} else if (newValue != null && newValue.isNotEmpty()) {
|
||||||
|
setDefaultValue(newValue.toInt(), update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMax(max: Int) {
|
||||||
|
mMaxValue = max
|
||||||
|
mSeekBar.max = mMaxValue - mMinValue
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMin(min: Int) {
|
||||||
|
mMinValue = min
|
||||||
|
mSeekBar.max = mMaxValue - mMinValue
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setValue(newValue: Int, update: Boolean) {
|
||||||
|
var newValue = newValue
|
||||||
|
newValue = getLimitedValue(newValue)
|
||||||
|
if (mValue != newValue) {
|
||||||
|
if (update) mSeekBar.progress = getSeekValue(newValue) else mValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// need some methods here to set/get other attrs at runtime,
|
||||||
|
var value: Int
|
||||||
|
get() = mValue
|
||||||
|
set(newValue) {
|
||||||
|
mValue = getLimitedValue(newValue)
|
||||||
|
mSeekBar.progress = getSeekValue(mValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// but who really need this ...
|
||||||
|
companion object {
|
||||||
|
private const val APP_NS = "http://schemas.android.com/apk/res-auto"
|
||||||
|
protected const val ANDROIDNS = "http://schemas.android.com/apk/res/android"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val a = context.obtainStyledAttributes(
|
||||||
|
attrs,
|
||||||
|
com.eurekateam.samsungextras.R.styleable.CustomSeekBarPreference
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
mShowSign = a.getBoolean(
|
||||||
|
com.eurekateam.samsungextras.R.styleable.CustomSeekBarPreference_showSign,
|
||||||
|
mShowSign
|
||||||
|
)
|
||||||
|
val units =
|
||||||
|
a.getString(com.eurekateam.samsungextras.R.styleable.CustomSeekBarPreference_units)
|
||||||
|
if (units != null) mUnits = " $units"
|
||||||
|
mContinuousUpdates = a.getBoolean(
|
||||||
|
com.eurekateam.samsungextras.R.styleable.CustomSeekBarPreference_continuousUpdates,
|
||||||
|
mContinuousUpdates
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
a.recycle()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val newInterval = attrs!!.getAttributeValue(APP_NS, "interval")
|
||||||
|
if (newInterval != null) mInterval = newInterval.toInt()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Invalid interval value", e)
|
||||||
|
}
|
||||||
|
mMinValue = attrs!!.getAttributeIntValue(APP_NS, "min", mMinValue)
|
||||||
|
mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", mMaxValue)
|
||||||
|
if (mMaxValue < mMinValue) mMaxValue = mMinValue
|
||||||
|
val defaultValue = attrs.getAttributeValue(ANDROIDNS, "defaultValue")
|
||||||
|
mDefaultValueExists = defaultValue != null && defaultValue.isNotEmpty()
|
||||||
|
if (mDefaultValueExists) {
|
||||||
|
mDefaultValue = getLimitedValue(defaultValue!!.toInt())
|
||||||
|
mValue = mDefaultValue
|
||||||
|
} else {
|
||||||
|
mValue = mMinValue
|
||||||
|
}
|
||||||
|
mSeekBar = SeekBar(context, attrs)
|
||||||
|
layoutResource = com.eurekateam.samsungextras.R.layout.preference_custom_seekbar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.preferences;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.preferences.SecureSettingsStore;
|
|
||||||
|
|
||||||
public class SecureSettingCustomSeekBarPreference extends com.eurekateam.samsungextras.preferences.CustomSeekBarPreference {
|
|
||||||
|
|
||||||
public SecureSettingCustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingCustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingCustomSeekBarPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingCustomSeekBarPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 AICP
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.preferences;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import androidx.preference.ListPreference;
|
|
||||||
|
|
||||||
public class SecureSettingListPreference extends ListPreference {
|
|
||||||
private boolean mAutoSummary = false;
|
|
||||||
|
|
||||||
public SecureSettingListPreference(Context context, AttributeSet attrs, int defStyle) {
|
|
||||||
super(context, attrs, defStyle);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingListPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingListPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(String value) {
|
|
||||||
super.setValue(value);
|
|
||||||
if (mAutoSummary || TextUtils.isEmpty(getSummary())) {
|
|
||||||
setSummary(getEntry(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSummary(CharSequence summary) {
|
|
||||||
setSummary(summary, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSummary(CharSequence summary, boolean autoSummary) {
|
|
||||||
mAutoSummary = autoSummary;
|
|
||||||
super.setSummary(summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
|
||||||
// This is what default ListPreference implementation is doing without respecting
|
|
||||||
// real default value:
|
|
||||||
//setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
|
|
||||||
// Instead, we better do
|
|
||||||
setValue(restoreValue ? getPersistedString((String) defaultValue) : (String) defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.eurekateam.samsungextras.preferences;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
public class SecureSettingSwitchPreference extends SwitchPreference {
|
|
||||||
public SecureSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
|
||||||
super(context, attrs, defStyle);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingSwitchPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecureSettingSwitchPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean persistBoolean(boolean value) {
|
|
||||||
if (shouldPersist()) {
|
|
||||||
if (value == getPersistedBoolean(!value)) {
|
|
||||||
// It's already there, so the same as persisting
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Settings.Secure.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean getPersistedBoolean(boolean defaultReturnValue) {
|
|
||||||
if (!shouldPersist()) {
|
|
||||||
return defaultReturnValue;
|
|
||||||
}
|
|
||||||
return Settings.Secure.getInt(getContext().getContentResolver(),
|
|
||||||
getKey(), defaultReturnValue ? 1 : 0) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
|
||||||
setChecked(Settings.Secure.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
|
|
||||||
: (Boolean) defaultValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 AICP
|
|
||||||
* Copyright (C) 2018 CarbonROM
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.preferences;
|
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.preference.PreferenceDataStore;
|
|
||||||
import android.provider.Settings;
|
|
||||||
|
|
||||||
public class SecureSettingsStore extends androidx.preference.PreferenceDataStore
|
|
||||||
implements PreferenceDataStore {
|
|
||||||
|
|
||||||
private final ContentResolver mContentResolver;
|
|
||||||
|
|
||||||
public SecureSettingsStore(ContentResolver contentResolver) {
|
|
||||||
mContentResolver = contentResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBoolean(String key, boolean defValue) {
|
|
||||||
return getInt(key, defValue ? 1 : 0) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getFloat(String key, float defValue) {
|
|
||||||
return Settings.Secure.getFloat(mContentResolver, key, defValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInt(String key, int defValue) {
|
|
||||||
return Settings.Secure.getInt(mContentResolver, key, defValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLong(String key, long defValue) {
|
|
||||||
return Settings.Secure.getLong(mContentResolver, key, defValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getString(String key, String defValue) {
|
|
||||||
String result = Settings.Secure.getString(mContentResolver, key);
|
|
||||||
return result == null ? defValue : result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putBoolean(String key, boolean value) {
|
|
||||||
putInt(key, value ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putFloat(String key, float value) {
|
|
||||||
Settings.Secure.putFloat(mContentResolver, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putInt(String key, int value) {
|
|
||||||
Settings.Secure.putInt(mContentResolver, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putLong(String key, long value) {
|
|
||||||
Settings.Secure.putLong(mContentResolver, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putString(String key, String value) {
|
|
||||||
Settings.Secure.putString(mContentResolver, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.speaker;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
public class ClearSpeakerActivity extends FragmentActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
|
|
||||||
ClearSpeakerFragment clearSpeakerFragment;
|
|
||||||
if (fragment == null) {
|
|
||||||
clearSpeakerFragment = new ClearSpeakerFragment();
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.add(android.R.id.content, clearSpeakerFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.speaker
|
||||||
|
|
||||||
|
import android.R.id.content
|
||||||
|
import android.R.id.home
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
|
||||||
|
class ClearSpeakerActivity : FragmentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
|
val fragment = fragmentManager.findFragmentById(content)
|
||||||
|
val clearSpeakerFragment: ClearSpeakerFragment
|
||||||
|
if (fragment == null) {
|
||||||
|
clearSpeakerFragment = ClearSpeakerFragment()
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(content, clearSpeakerFragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == home) {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Paranoid Android
|
|
||||||
*
|
|
||||||
* 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.eurekateam.samsungextras.speaker;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.AssetFileDescriptor;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.media.MediaPlayer;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceFragment;
|
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.R;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class ClearSpeakerFragment extends PreferenceFragment implements
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
|
|
||||||
private static final String TAG = ClearSpeakerFragment.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final String PREF_CLEAR_SPEAKER = "clear_speaker_pref";
|
|
||||||
|
|
||||||
private AudioManager mAudioManager;
|
|
||||||
private Handler mHandler;
|
|
||||||
private MediaPlayer mMediaPlayer;
|
|
||||||
private SwitchPreference mClearSpeakerPref;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
addPreferencesFromResource(R.xml.clear_speaker_settings);
|
|
||||||
|
|
||||||
mClearSpeakerPref = findPreference(PREF_CLEAR_SPEAKER);
|
|
||||||
mClearSpeakerPref.setOnPreferenceChangeListener(this);
|
|
||||||
|
|
||||||
mHandler = new Handler();
|
|
||||||
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
if (preference == mClearSpeakerPref) {
|
|
||||||
boolean value = (Boolean) newValue;
|
|
||||||
if (value) {
|
|
||||||
if (startPlaying()) {
|
|
||||||
mHandler.removeCallbacksAndMessages(null);
|
|
||||||
mHandler.postDelayed(this::stopPlaying, 30000);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop() {
|
|
||||||
stopPlaying();
|
|
||||||
super.onStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start playing speaker-clearing audio
|
|
||||||
* @return true on success, else false
|
|
||||||
*/
|
|
||||||
public boolean startPlaying() {
|
|
||||||
mAudioManager.setParameters("status_earpiece_clean=on");
|
|
||||||
mMediaPlayer = new MediaPlayer();
|
|
||||||
getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
|
||||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
|
||||||
mMediaPlayer.setLooping(true);
|
|
||||||
try {
|
|
||||||
try (AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.clear_speaker_sound)) {
|
|
||||||
mMediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
|
|
||||||
}
|
|
||||||
mClearSpeakerPref.setEnabled(false);
|
|
||||||
mMediaPlayer.setVolume(1.0f, 1.0f);
|
|
||||||
mMediaPlayer.prepare();
|
|
||||||
mMediaPlayer.start();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.e(TAG, "Failed to play speaker clean sound!", ioe);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops and invalidates
|
|
||||||
*/
|
|
||||||
public void stopPlaying() {
|
|
||||||
if (mMediaPlayer != null) {
|
|
||||||
mMediaPlayer.stop();
|
|
||||||
mMediaPlayer.reset();
|
|
||||||
mMediaPlayer.release();
|
|
||||||
}
|
|
||||||
mAudioManager.setParameters("status_earpiece_clean=off");
|
|
||||||
mClearSpeakerPref.setEnabled(true);
|
|
||||||
mClearSpeakerPref.setChecked(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.eurekateam.samsungextras.speaker
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragment
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import com.eurekateam.samsungextras.R
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class ClearSpeakerFragment : PreferenceFragment(), Preference.OnPreferenceChangeListener {
|
||||||
|
private var mAudioManager: AudioManager? = null
|
||||||
|
private var mHandler: Handler? = null
|
||||||
|
private var mMediaPlayer: MediaPlayer? = null
|
||||||
|
private var mClearSpeakerPref: SwitchPreference? = null
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
addPreferencesFromResource(R.xml.clear_speaker_settings)
|
||||||
|
mClearSpeakerPref = findPreference(PREF_CLEAR_SPEAKER)
|
||||||
|
mClearSpeakerPref!!.onPreferenceChangeListener = this
|
||||||
|
mHandler = Handler(Looper.getMainLooper())
|
||||||
|
mAudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
if (preference === mClearSpeakerPref) {
|
||||||
|
val value = newValue as Boolean
|
||||||
|
if (value) {
|
||||||
|
if (startPlaying()) {
|
||||||
|
mHandler!!.removeCallbacksAndMessages(null)
|
||||||
|
mHandler!!.postDelayed({ stopPlaying() }, 30000)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
stopPlaying()
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start playing speaker-clearing audio
|
||||||
|
* @return true on success, else false
|
||||||
|
*/
|
||||||
|
private fun startPlaying(): Boolean {
|
||||||
|
mAudioManager!!.setParameters("status_earpiece_clean=on")
|
||||||
|
mMediaPlayer = MediaPlayer()
|
||||||
|
activity.volumeControlStream = AudioManager.STREAM_MUSIC
|
||||||
|
mMediaPlayer!!.setAudioStreamType(AudioManager.STREAM_MUSIC)
|
||||||
|
mMediaPlayer!!.isLooping = true
|
||||||
|
try {
|
||||||
|
resources.openRawResourceFd(R.raw.clear_speaker_sound).use { file ->
|
||||||
|
mMediaPlayer!!.setDataSource(
|
||||||
|
file.fileDescriptor,
|
||||||
|
file.startOffset,
|
||||||
|
file.length
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mClearSpeakerPref!!.isEnabled = false
|
||||||
|
mMediaPlayer!!.setVolume(1.0f, 1.0f)
|
||||||
|
mMediaPlayer!!.prepare()
|
||||||
|
mMediaPlayer!!.start()
|
||||||
|
} catch (ioe: IOException) {
|
||||||
|
Log.e(TAG, "Failed to play speaker clean sound!", ioe)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops and invalidates
|
||||||
|
*/
|
||||||
|
private fun stopPlaying() {
|
||||||
|
if (mMediaPlayer != null) {
|
||||||
|
mMediaPlayer!!.stop()
|
||||||
|
mMediaPlayer!!.reset()
|
||||||
|
mMediaPlayer!!.release()
|
||||||
|
}
|
||||||
|
mAudioManager!!.setParameters("status_earpiece_clean=off")
|
||||||
|
mClearSpeakerPref!!.isEnabled = true
|
||||||
|
mClearSpeakerPref!!.isChecked = false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = ClearSpeakerFragment::class.java.simpleName
|
||||||
|
private const val PREF_CLEAR_SPEAKER = "clear_speaker_pref"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.utils;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.os.FileUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
|
|
||||||
public final class FileUtilsWrapper {
|
|
||||||
private static final String TAG = "FileUtils";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the first line of text from the given file.
|
|
||||||
* Reference {@link FileUtils} for clarification on what a line is
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static String readOneLine(String fileName){
|
|
||||||
try {
|
|
||||||
return FileUtils.readTextFile(new File(fileName),0,null)
|
|
||||||
.replaceAll("[\n]","");
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given value into the given file
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static void writeLine(String fileName, String value){
|
|
||||||
try {
|
|
||||||
FileUtils.stringToFile(fileName,value);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the given file exists
|
|
||||||
*
|
|
||||||
* @return true if exists, false if not
|
|
||||||
*/
|
|
||||||
public static boolean fileExists(String fileName) {
|
|
||||||
final File file = new File(fileName);
|
|
||||||
return file.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the given file is readable
|
|
||||||
*
|
|
||||||
* @return true if readable, false if not
|
|
||||||
*/
|
|
||||||
public static boolean isFileReadable(String fileName) {
|
|
||||||
final File file = new File(fileName);
|
|
||||||
return file.exists() && file.canRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the given file is writable
|
|
||||||
*
|
|
||||||
* @return true if writable, false if not
|
|
||||||
*/
|
|
||||||
public static boolean isFileWritable(String fileName) {
|
|
||||||
final File file = new File(fileName);
|
|
||||||
return file.exists() && file.canWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes an existing file
|
|
||||||
*
|
|
||||||
* @return true if the delete was successful, false if not
|
|
||||||
*/
|
|
||||||
public static boolean delete(String fileName) {
|
|
||||||
final File file = new File(fileName);
|
|
||||||
boolean ok = false;
|
|
||||||
try {
|
|
||||||
ok = file.delete();
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
Log.w(TAG, "SecurityException trying to delete " + fileName, e);
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames an existing file
|
|
||||||
*
|
|
||||||
* @return true if the rename was successful, false if not
|
|
||||||
*/
|
|
||||||
public static boolean rename(String srcPath, String dstPath) {
|
|
||||||
final File srcFile = new File(srcPath);
|
|
||||||
final File dstFile = new File(dstPath);
|
|
||||||
boolean ok = false;
|
|
||||||
try {
|
|
||||||
ok = srcFile.renameTo(dstFile);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
Log.w(TAG, "SecurityException trying to rename " + srcPath + " to " + dstPath, e);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
Log.e(TAG, "NullPointerException trying to rename " + srcPath + " to " + dstPath, e);
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
package com.eurekateam.samsungextras.utils;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.eurekateam.samsungextras.GlobalConstants;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
public class SystemProperties {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To read a prop using getprop
|
|
||||||
* @param propName the prop name to get
|
|
||||||
* @return the prop's value, empty string is not found
|
|
||||||
*/
|
|
||||||
public static String read(String propName) {
|
|
||||||
Process process = null;
|
|
||||||
BufferedReader bufferedReader = null;
|
|
||||||
|
|
||||||
String TAG = GlobalConstants.TAG;
|
|
||||||
try {
|
|
||||||
String GETPROP_EXECUTABLE_PATH = "/system/bin/getprop";
|
|
||||||
process = new ProcessBuilder().command(GETPROP_EXECUTABLE_PATH, propName).redirectErrorStream(true).start();
|
|
||||||
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
String line = bufferedReader.readLine();
|
|
||||||
if (line == null){
|
|
||||||
line = ""; //prop not set
|
|
||||||
}
|
|
||||||
Log.i(TAG,"read System Property: " + propName + "=" + line);
|
|
||||||
return line;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG,"Failed to read System Property " + propName,e);
|
|
||||||
return "";
|
|
||||||
} finally{
|
|
||||||
if (bufferedReader != null){
|
|
||||||
try {
|
|
||||||
bufferedReader.close();
|
|
||||||
} catch (IOException ignored) {}
|
|
||||||
}
|
|
||||||
if (process != null){
|
|
||||||
process.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The status of SELinux on the device
|
|
||||||
* true: enforcing, false: permissive
|
|
||||||
*/
|
|
||||||
public static boolean getenforce() {
|
|
||||||
Process process = null;
|
|
||||||
BufferedReader bufferedReader;
|
|
||||||
String TAG = GlobalConstants.TAG;
|
|
||||||
try {
|
|
||||||
String GETENFORCE_EXECUTABLE_PATH = "/system/bin/getenforce";
|
|
||||||
process = new ProcessBuilder().command(GETENFORCE_EXECUTABLE_PATH).redirectErrorStream(true).start();
|
|
||||||
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
String line = bufferedReader.readLine();
|
|
||||||
if (line == null) {
|
|
||||||
line = ""; //prop not set
|
|
||||||
}
|
|
||||||
Log.i(TAG, "Getenforce: " + line);
|
|
||||||
return line.equals("Enforcing");
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Getenforce failed", e);
|
|
||||||
} finally {
|
|
||||||
if (process != null) {
|
|
||||||
process.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.eurekateam.samsungextras.utils
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.eurekateam.samsungextras.GlobalConstants
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
|
||||||
|
object SystemProperties {
|
||||||
|
/**
|
||||||
|
* To read a prop using getprop
|
||||||
|
* @param propName the prop name to get
|
||||||
|
* @return the prop's value, empty string is not found
|
||||||
|
*/
|
||||||
|
fun read(propName: String): String {
|
||||||
|
var process: Process? = null
|
||||||
|
var bufferedReader: BufferedReader? = null
|
||||||
|
val TAG = GlobalConstants.TAG
|
||||||
|
return try {
|
||||||
|
val GETPROP_EXECUTABLE_PATH = "/system/bin/getprop"
|
||||||
|
process = ProcessBuilder().command(GETPROP_EXECUTABLE_PATH, propName)
|
||||||
|
.redirectErrorStream(true).start()
|
||||||
|
bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
|
||||||
|
var line = bufferedReader.readLine()
|
||||||
|
if (line == null) {
|
||||||
|
line = "" //prop not set
|
||||||
|
}
|
||||||
|
Log.i(TAG, "read System Property: $propName=$line")
|
||||||
|
line
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to read System Property $propName", e)
|
||||||
|
""
|
||||||
|
} finally {
|
||||||
|
if (bufferedReader != null) {
|
||||||
|
try {
|
||||||
|
bufferedReader.close()
|
||||||
|
} catch (ignored: IOException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process?.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue