samsung: doze: Apply a major refactor

* Introduce a main switch to actually enable/disable doze globally
 * Move preferences handling out of SamsungDozeService class and
   create Utils class to hold all helper methods.

Change-Id: Idb40650296d50352b4a985d2068f14cda6cb4aaf
This commit is contained in:
Bruno Martins 2020-12-26 14:55:22 +00:00
parent 8449b50d22
commit 4a3c87d088
15 changed files with 413 additions and 118 deletions

View file

@ -30,4 +30,6 @@ ifneq ($(INCREMENTAL_BUILDS),)
LOCAL_JACK_ENABLED := incremental
endif
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019-2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/switchbar_background_color" android:state_activated="false" />
<item android:color="?android:attr/colorAccent" android:state_activated="true" />
</selector>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/switch_bar_bg" />
</shape>

28
doze/res/layout/doze.xml Normal file
View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2014, The Android Open Source 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.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<include layout="@layout/switch_bar" />
</LinearLayout>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/switch_bar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@drawable/switchbar_background"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:clickable="true"
android:gravity="center"
android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
<TextView android:id="@+id/switch_text"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:paddingStart="56dp"
android:maxLines="2"
android:ellipsize="end"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="?android:attr/textColorPrimaryInverse"
android:textSize="18sp"
android:textAlignment="viewStart" />
<Switch
android:id="@android:id/switch_widget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
android:theme="@style/Theme.Main.SwitchBar.Switch" />
</LinearLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<color name="switchbar_switch_track_tint">#82000000</color>
<color name="switchbar_switch_thumb_tint">@android:color/black</color>
</resources>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<color name="switchbar_background_color">@*android:color/material_grey_600</color>
<color name="switchbar_switch_track_tint">#BFFFFFFF</color>
<color name="switchbar_switch_thumb_tint">@android:color/white</color>
</resources>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The CyanogenMod Project
Copyright (C) 2015-2016 The CyanogenMod Project
2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -44,7 +45,10 @@
<item name="android:layout">@layout/preference_material_settings</item>
</style>
<style name="Theme.Main.PreferenceTheme">
<style name="Theme.Main.PreferenceTheme" parent="@style/PreferenceThemeOverlay.SettingsBase">
<item name="preferenceCategoryTitleTextAppearance">
@style/Theme.Main.TextAppearance.CategoryTitle
</item>
</style>
<style name="Theme.Main.SwitchPreferenceStyle" parent="@style/Theme.Main.PreferenceStyle">
@ -53,4 +57,17 @@
<style name="Theme.Main.SwitchBar" parent="@android:style/ThemeOverlay.Material.ActionBar">
</style>
<style name="Theme.Main.SwitchBar.Switch">
<item name="android:trackTint">@color/switchbar_switch_track_tint</item>
<item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
</style>
<style name="Theme.Main.TextAppearance.CategoryTitle"
parent="@*android:style/TextAppearance.DeviceDefault.Body2">
<item name="android:textAllCaps">true</item>
<item name="android:textSize">11sp</item>
<!-- 0.8 Spacing, 0.8/11 = 0.072727273 -->
<item name="android:letterSpacing">0.072727273</item>
</style>
</resources>

View file

@ -17,28 +17,20 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="ambient_display_key"
android:title="@string/ambient_display_title">
<lineageos.preference.SecureSettingSwitchPreference
android:key="doze_enabled"
android:defaultValue="true"
android:title="@string/ambient_display_enable_title"
android:summary="@string/ambient_display_enable_summary" />
android:key="proximity_sensor"
android:title="@string/proximity_sensor_title">
<SwitchPreference
android:key="gesture_hand_wave"
android:defaultValue="false"
android:title="@string/hand_wave_gesture_title"
android:summary="@string/hand_wave_gesture_summary"
android:dependency="doze_enabled" />
android:summary="@string/hand_wave_gesture_summary" />
<SwitchPreference
android:key="gesture_pocket"
android:defaultValue="false"
android:title="@string/pocket_gesture_title"
android:summary="@string/pocket_gesture_summary"
android:dependency="doze_enabled" />
android:summary="@string/pocket_gesture_summary" />
</PreferenceCategory>
</PreferenceScreen>

View file

@ -28,8 +28,8 @@ public class BootCompletedReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Starting service");
context.startService(new Intent(context, SamsungDozeService.class));
if (DEBUG) Log.d(TAG, "Received boot completed intent");
Utils.checkDozeService(context);
}
}

View file

@ -26,6 +26,6 @@ public class SamsungDozeActivity extends PreferenceActivity {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content,
new TouchscreenGestureSettings(), TAG).commit();
new SamsungDozeSettings(), TAG).commit();
}
}

View file

@ -21,7 +21,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@ -29,24 +28,14 @@ import android.hardware.SensorManager;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.UserHandle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import java.lang.System;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.List;
public class SamsungDozeService extends Service {
private static final String TAG = "SamsungDozeService";
private static final boolean DEBUG = false;
private static final String DOZE_INTENT = "com.android.systemui.doze.pulse";
private static final String GESTURE_HAND_WAVE_KEY = "gesture_hand_wave";
private static final String GESTURE_POCKET_KEY = "gesture_pocket";
private static final int POCKET_DELTA_NS = 1000 * 1000 * 1000;
private Context mContext;
@ -64,7 +53,7 @@ public class SamsungDozeService extends Service {
private long mInPocketTime = 0;
public SamsungProximitySensor(Context context) {
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
mSensorManager = context.getSystemService(SensorManager.class);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
}
@ -89,20 +78,21 @@ public class SamsungDozeService extends Service {
private boolean shouldPulse(long timestamp) {
long delta = timestamp - mInPocketTime;
if (mHandwaveGestureEnabled && mPocketGestureEnabled) {
if (Utils.isHandwaveGestureEnabled(mContext) &&
Utils.isPocketGestureEnabled(mContext)) {
return true;
} else if (mHandwaveGestureEnabled && !mPocketGestureEnabled) {
} else if (Utils.isHandwaveGestureEnabled(mContext) &&
!Utils.isPocketGestureEnabled(mContext)) {
return delta < POCKET_DELTA_NS;
} else if (!mHandwaveGestureEnabled && mPocketGestureEnabled) {
} else if (!Utils.isHandwaveGestureEnabled(mContext) &&
Utils.isPocketGestureEnabled(mContext)) {
return delta >= POCKET_DELTA_NS;
}
return false;
}
public void testAndEnable() {
if ((isDozeEnabled() && (mHandwaveGestureEnabled || mPocketGestureEnabled)) {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void enable() {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void disable() {
@ -114,13 +104,10 @@ public class SamsungDozeService extends Service {
public void onCreate() {
if (DEBUG) Log.d(TAG, "SamsungDozeService Started");
mContext = this;
mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
mPowerManager = getSystemService(PowerManager.class);
mSensor = new SamsungProximitySensor(mContext);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
loadPreferences(sharedPrefs);
sharedPrefs.registerOnSharedPreferenceChangeListener(mPrefListener);
if (!isInteractive()) {
mSensor.testAndEnable();
mSensor.enable();
}
}
@ -147,11 +134,6 @@ public class SamsungDozeService extends Service {
return mPowerManager.isInteractive();
}
private boolean isDozeEnabled() {
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.DOZE_ENABLED, 1) != 0;
}
private void onDisplayOn() {
if (DEBUG) Log.d(TAG, "Display on");
mSensor.disable();
@ -159,12 +141,7 @@ public class SamsungDozeService extends Service {
private void onDisplayOff() {
if (DEBUG) Log.d(TAG, "Display off");
mSensor.testAndEnable();
}
private void loadPreferences(SharedPreferences sharedPreferences) {
mHandwaveGestureEnabled = sharedPreferences.getBoolean(GESTURE_HAND_WAVE_KEY, false);
mPocketGestureEnabled = sharedPreferences.getBoolean(GESTURE_POCKET_KEY, false);
mSensor.enable();
}
private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
@ -177,16 +154,4 @@ public class SamsungDozeService extends Service {
}
}
};
private SharedPreferences.OnSharedPreferenceChangeListener mPrefListener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (GESTURE_HAND_WAVE_KEY.equals(key)) {
mHandwaveGestureEnabled = sharedPreferences.getBoolean(GESTURE_HAND_WAVE_KEY, false);
} else if (GESTURE_POCKET_KEY.equals(key)) {
mPocketGestureEnabled = sharedPreferences.getBoolean(GESTURE_POCKET_KEY, false);
}
}
};
}

View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 2015 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 org.lineageos.settings.doze;
import android.app.ActionBar;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragment;
import androidx.preference.SwitchPreference;
import org.lineageos.internal.util.ScreenType;
public class SamsungDozeSettings extends PreferenceFragment
implements CompoundButton.OnCheckedChangeListener, Preference.OnPreferenceChangeListener {
private TextView mTextView;
private View mSwitchBar;
private SwitchPreference mHandwavePreference;
private SwitchPreference mPocketPreference;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.gesture_panel);
final ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
boolean dozeEnabled = Utils.isDozeEnabled(getActivity());
mHandwavePreference = findPreference(Utils.GESTURE_HAND_WAVE_KEY);
mHandwavePreference.setEnabled(dozeEnabled);
mHandwavePreference.setOnPreferenceChangeListener(this);
mPocketPreference = findPreference(Utils.GESTURE_POCKET_KEY);
mPocketPreference.setEnabled(dozeEnabled);
mPocketPreference.setOnPreferenceChangeListener(this);
}
@Override
public void onResume() {
super.onResume();
// If running on a phone, remove padding around the listview
if (!ScreenType.isTablet(getContext())) {
getListView().setPadding(0, 0, 0, 0);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view =
LayoutInflater.from(getContext()).inflate(R.layout.doze, container, false);
((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
boolean dozeEnabled = Utils.isDozeEnabled(getActivity());
mTextView = view.findViewById(R.id.switch_text);
mTextView.setText(getString(dozeEnabled ?
R.string.switch_bar_on : R.string.switch_bar_off));
mSwitchBar = view.findViewById(R.id.switch_bar);
Switch switchWidget = mSwitchBar.findViewById(android.R.id.switch_widget);
switchWidget.setChecked(dozeEnabled);
switchWidget.setOnCheckedChangeListener(this);
mSwitchBar.setActivated(dozeEnabled);
mSwitchBar.setOnClickListener(v -> {
switchWidget.setChecked(!switchWidget.isChecked());
mSwitchBar.setActivated(switchWidget.isChecked());
});
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Utils.enableGesture(getActivity(), preference.getKey(), (Boolean) newValue);
Utils.checkDozeService(getActivity());
return true;
}
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
Utils.enableDoze(getActivity(), isChecked);
Utils.checkDozeService(getActivity());
mTextView.setText(getString(isChecked ? R.string.switch_bar_on : R.string.switch_bar_off));
mSwitchBar.setActivated(isChecked);
mHandwavePreference.setEnabled(isChecked);
mPocketPreference.setEnabled(isChecked);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
getActivity().onBackPressed();
return true;
}
return false;
}
}

View file

@ -1,54 +0,0 @@
/*
* Copyright (C) 2015 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 org.lineageos.settings.doze;
import android.app.ActionBar;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.preference.PreferenceFragment;
import org.lineageos.internal.util.ScreenType;
public class TouchscreenGestureSettings extends PreferenceFragment {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.gesture_panel);
final ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
@Override
public void onResume() {
super.onResume();
// If running on a phone, remove padding around the listview
if (!ScreenType.isTablet(getContext())) {
getListView().setPadding(0, 0, 0, 0);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
getActivity().onBackPressed();
return true;
}
return false;
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* 2017-2019 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.doze;
import static android.provider.Settings.Secure.DOZE_ENABLED;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import androidx.preference.PreferenceManager;
public final class Utils {
private static final String TAG = "DozeUtils";
private static final boolean DEBUG = false;
protected static final String GESTURE_HAND_WAVE_KEY = "gesture_hand_wave";
protected static final String GESTURE_POCKET_KEY = "gesture_pocket";
protected static void startService(Context context) {
if (DEBUG) Log.d(TAG, "Starting service");
context.startServiceAsUser(new Intent(context, SamsungDozeService.class),
UserHandle.CURRENT);
}
protected static void stopService(Context context) {
if (DEBUG) Log.d(TAG, "Stopping service");
context.stopServiceAsUser(new Intent(context, SamsungDozeService.class),
UserHandle.CURRENT);
}
protected static void checkDozeService(Context context) {
if (isDozeEnabled(context) && isAnyGestureEnabled(context)) {
startService(context);
} else {
stopService(context);
}
}
protected static boolean isDozeEnabled(Context context) {
return Settings.Secure.getInt(context.getContentResolver(),
DOZE_ENABLED, 1) != 0;
}
protected static boolean enableDoze(Context context, boolean enable) {
return Settings.Secure.putInt(context.getContentResolver(),
DOZE_ENABLED, enable ? 1 : 0);
}
protected static void enableGesture(Context context, String gesture, boolean enable) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putBoolean(gesture, enable).apply();
}
protected static boolean isAnyGestureEnabled(Context context) {
return isHandwaveGestureEnabled(context) || isPocketGestureEnabled(context);
}
protected static boolean isHandwaveGestureEnabled(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(GESTURE_HAND_WAVE_KEY, false);
}
protected static boolean isPocketGestureEnabled(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(GESTURE_POCKET_KEY, false);
}
}