sdk: Introduce LineagePreferenceLib
Because of some nested dependency breakage, we can no longer include Android libraries in main SDK lib, therefore we are moving all preference related code to a separate package that Settings/LineageParts will depend on. Change-Id: Iea379a580a08ea13f71e3503aa096ba0ed7e7cef
This commit is contained in:
@@ -1,418 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* 2017,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.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import lineageos.hardware.LineageHardwareManager;
|
||||
import lineageos.platform.R;
|
||||
|
||||
|
||||
/**
|
||||
* Helpers for checking if a device supports various features.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ConstraintsHelper {
|
||||
|
||||
private static final String TAG = "ConstraintsHelper";
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private final AttributeSet mAttrs;
|
||||
|
||||
private final Preference mPref;
|
||||
|
||||
private boolean mAvailable = true;
|
||||
|
||||
private boolean mVerifyIntent = true;
|
||||
|
||||
private int mSummaryMinLines = -1;
|
||||
|
||||
private String[] mReplacesKey = null;
|
||||
|
||||
public ConstraintsHelper(Context context, AttributeSet attrs, Preference pref) {
|
||||
mContext = context;
|
||||
mAttrs = attrs;
|
||||
mPref = pref;
|
||||
|
||||
TypedArray a = context.getResources().obtainAttributes(attrs,
|
||||
R.styleable.lineage_SelfRemovingPreference);
|
||||
mSummaryMinLines = a.getInteger(R.styleable.lineage_SelfRemovingPreference_minSummaryLines, -1);
|
||||
String replacesKey = a.getString(R.styleable.lineage_SelfRemovingPreference_replacesKey);
|
||||
if (replacesKey != null) {
|
||||
mReplacesKey = replacesKey.split("\\|");
|
||||
}
|
||||
setAvailable(checkConstraints());
|
||||
|
||||
Log.d(TAG, "construct key=" + mPref.getKey() + " available=" + mAvailable);
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
mAvailable = available;
|
||||
if (!available) {
|
||||
Graveyard.get(mContext).addTombstone(mPref.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return mAvailable;
|
||||
}
|
||||
|
||||
public void setVerifyIntent(boolean verifyIntent) {
|
||||
mVerifyIntent = verifyIntent;
|
||||
}
|
||||
|
||||
private PreferenceGroup getParent(Preference preference) {
|
||||
return getParent(mPref.getPreferenceManager().getPreferenceScreen(), preference);
|
||||
}
|
||||
|
||||
private PreferenceGroup getParent(PreferenceGroup root, Preference preference) {
|
||||
for (int i = 0; i < root.getPreferenceCount(); i++) {
|
||||
Preference p = root.getPreference(i);
|
||||
if (p == preference)
|
||||
return root;
|
||||
if (PreferenceGroup.class.isInstance(p)) {
|
||||
PreferenceGroup parent = getParent((PreferenceGroup) p, preference);
|
||||
if (parent != null)
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isNegated(String key) {
|
||||
return key != null && key.startsWith("!");
|
||||
}
|
||||
|
||||
private void checkIntent() {
|
||||
Intent i = mPref.getIntent();
|
||||
if (i != null) {
|
||||
if (!resolveIntent(mContext, i)) {
|
||||
Graveyard.get(mContext).addTombstone(mPref.getKey());
|
||||
mAvailable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkConstraints() {
|
||||
if (mAttrs == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TypedArray a = mContext.getResources().obtainAttributes(mAttrs,
|
||||
R.styleable.lineage_SelfRemovingPreference);
|
||||
|
||||
try {
|
||||
|
||||
// Check if the current user is an owner
|
||||
boolean rOwner = a.getBoolean(R.styleable.lineage_SelfRemovingPreference_requiresOwner, false);
|
||||
if (rOwner && UserHandle.myUserId() != UserHandle.USER_SYSTEM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a specific package is installed
|
||||
String rPackage = a.getString(R.styleable.lineage_SelfRemovingPreference_requiresPackage);
|
||||
if (rPackage != null) {
|
||||
boolean negated = isNegated(rPackage);
|
||||
if (negated) {
|
||||
rPackage = rPackage.substring(1);
|
||||
}
|
||||
boolean available = isPackageInstalled(mContext, rPackage, false);
|
||||
if (available == negated) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if an intent can be resolved to handle the given action
|
||||
String rAction = a.getString(R.styleable.lineage_SelfRemovingPreference_requiresAction);
|
||||
if (rAction != null) {
|
||||
boolean negated = isNegated(rAction);
|
||||
if (negated) {
|
||||
rAction = rAction.substring(1);
|
||||
}
|
||||
boolean available = resolveIntent(mContext, rAction);
|
||||
if (available == negated) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a system feature is available
|
||||
String rFeature = a.getString(R.styleable.lineage_SelfRemovingPreference_requiresFeature);
|
||||
if (rFeature != null) {
|
||||
boolean negated = isNegated(rFeature);
|
||||
if (negated) {
|
||||
rFeature = rFeature.substring(1);
|
||||
}
|
||||
boolean available = rFeature.startsWith("lineagehardware:") ?
|
||||
LineageHardwareManager.getInstance(mContext).isSupported(
|
||||
rFeature.substring("lineagehardware:".length())) :
|
||||
hasSystemFeature(mContext, rFeature);
|
||||
if (available == negated) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check a boolean system property
|
||||
String rProperty = a.getString(R.styleable.lineage_SelfRemovingPreference_requiresProperty);
|
||||
if (rProperty != null) {
|
||||
boolean negated = isNegated(rProperty);
|
||||
if (negated) {
|
||||
rProperty = rProperty.substring(1);
|
||||
}
|
||||
String value = SystemProperties.get(rProperty);
|
||||
boolean available = value != null && Boolean.parseBoolean(value);
|
||||
if (available == negated) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check a config resource. This can be a bool, string or integer.
|
||||
// The preference is removed if any of the following are true:
|
||||
// * A bool resource is false.
|
||||
// * A string resource is null.
|
||||
// * An integer resource is zero.
|
||||
// * An integer is non-zero and when bitwise logically ANDed with
|
||||
// attribute requiresConfigMask, the result is zero.
|
||||
TypedValue tv = a.peekValue(R.styleable.lineage_SelfRemovingPreference_requiresConfig);
|
||||
if (tv != null && tv.resourceId != 0) {
|
||||
if (tv.type == TypedValue.TYPE_STRING &&
|
||||
mContext.getResources().getString(tv.resourceId) == null) {
|
||||
return false;
|
||||
} else if (tv.type == TypedValue.TYPE_INT_BOOLEAN && tv.data == 0) {
|
||||
return false;
|
||||
} else if (tv.type == TypedValue.TYPE_INT_DEC) {
|
||||
int mask = a.getInt(
|
||||
R.styleable.lineage_SelfRemovingPreference_requiresConfigMask, -1);
|
||||
if (tv.data == 0 || (mask >= 0 && (tv.data & mask) == 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the device supports a particular feature
|
||||
*/
|
||||
public static boolean hasSystemFeature(Context context, String feature) {
|
||||
return context.getPackageManager().hasSystemFeature(feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the device is voice-capable (meaning, it is also a phone).
|
||||
*/
|
||||
public static boolean isVoiceCapable(Context context) {
|
||||
TelephonyManager telephony =
|
||||
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
return telephony != null && telephony.isVoiceCapable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a package is installed. Set the ignoreState argument to true if you don't
|
||||
* care if the package is enabled/disabled.
|
||||
*/
|
||||
public static boolean isPackageInstalled(Context context, String pkg, boolean ignoreState) {
|
||||
if (pkg != null) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(pkg, 0);
|
||||
if (!pi.applicationInfo.enabled && !ignoreState) {
|
||||
return false;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a package is available to handle the given action.
|
||||
*/
|
||||
public static boolean resolveIntent(Context context, Intent intent) {
|
||||
if (DEBUG) Log.d(TAG, "resolveIntent " + Objects.toString(intent));
|
||||
// check whether the target handler exist in system
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
|
||||
PackageManager.MATCH_SYSTEM_ONLY,
|
||||
UserHandle.myUserId());
|
||||
for (ResolveInfo resolveInfo : results) {
|
||||
// check is it installed in system.img, exclude the application
|
||||
// installed by user
|
||||
if (DEBUG) Log.d(TAG, "resolveInfo: " + Objects.toString(resolveInfo));
|
||||
if ((resolveInfo.activityInfo.applicationInfo.flags &
|
||||
ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean resolveIntent(Context context, String action) {
|
||||
return resolveIntent(context, new Intent(action));
|
||||
}
|
||||
|
||||
public static int getAttr(Context context, int attr, int fallbackAttr) {
|
||||
TypedValue value = new TypedValue();
|
||||
context.getTheme().resolveAttribute(attr, value, true);
|
||||
if (value.resourceId != 0) {
|
||||
return attr;
|
||||
}
|
||||
return fallbackAttr;
|
||||
}
|
||||
|
||||
public void onAttached() {
|
||||
checkIntent();
|
||||
|
||||
if (isAvailable() && mReplacesKey != null) {
|
||||
Graveyard.get(mContext).addTombstones(mReplacesKey);
|
||||
}
|
||||
|
||||
Graveyard.get(mContext).summonReaper(mPref.getPreferenceManager());
|
||||
}
|
||||
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
if (!isAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSummaryMinLines > 0) {
|
||||
TextView textView = (TextView) holder.itemView.findViewById(android.R.id.summary);
|
||||
if (textView != null) {
|
||||
textView.setMinLines(mSummaryMinLines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we want to keep this at the preference level vs the fragment level, we need to
|
||||
* collate all the preferences that need to be removed when attached to the
|
||||
* hierarchy, then purge them all when loading is complete. The Graveyard keeps track
|
||||
* of this, and will reap the dead when onAttached is called.
|
||||
*/
|
||||
private static class Graveyard {
|
||||
|
||||
private Set<String> mDeathRow = new ArraySet<>();
|
||||
|
||||
private static Graveyard sInstance;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private Graveyard(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public synchronized static Graveyard get(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new Graveyard(context);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void addTombstone(String pref) {
|
||||
synchronized (mDeathRow) {
|
||||
mDeathRow.add(pref);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTombstones(String[] prefs) {
|
||||
synchronized (mDeathRow) {
|
||||
mDeathRow.addAll(Arrays.asList(prefs));
|
||||
}
|
||||
}
|
||||
|
||||
private PreferenceGroup getParent(Preference p1, Preference p2) {
|
||||
return getParent(p1.getPreferenceManager().getPreferenceScreen(), p2);
|
||||
}
|
||||
|
||||
private PreferenceGroup getParent(PreferenceGroup root, Preference preference) {
|
||||
for (int i = 0; i < root.getPreferenceCount(); i++) {
|
||||
Preference p = root.getPreference(i);
|
||||
if (p == preference)
|
||||
return root;
|
||||
if (PreferenceGroup.class.isInstance(p)) {
|
||||
PreferenceGroup parent = getParent((PreferenceGroup) p, preference);
|
||||
if (parent != null)
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void hidePreference(PreferenceManager mgr, Preference pref) {
|
||||
pref.setVisible(false);
|
||||
// Hide the group if nothing is visible
|
||||
final PreferenceGroup group = getParent(pref, pref);
|
||||
boolean allHidden = true;
|
||||
for (int i = 0; i < group.getPreferenceCount(); i++) {
|
||||
if (group.getPreference(i).isVisible()) {
|
||||
allHidden = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allHidden) {
|
||||
group.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void summonReaper(PreferenceManager mgr) {
|
||||
synchronized (mDeathRow) {
|
||||
Set<String> notReadyForReap = new ArraySet<>();
|
||||
for (String dead : mDeathRow) {
|
||||
Preference deadPref = mgr.findPreference(dead);
|
||||
if (deadPref != null) {
|
||||
hidePreference(mgr, deadPref);
|
||||
} else {
|
||||
notReadyForReap.add(dead);
|
||||
}
|
||||
}
|
||||
mDeathRow = notReadyForReap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
public class GlobalSettingMainSwitchPreference extends MainSwitchPreference {
|
||||
|
||||
public GlobalSettingMainSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public GlobalSettingMainSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public GlobalSettingMainSwitchPreference(Context context) {
|
||||
super(context, null);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
Settings.Global.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return Settings.Global.getInt(getContext().getContentResolver(), key,
|
||||
defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class GlobalSettingSwitchPreference extends SelfRemovingSwitchPreference {
|
||||
|
||||
public GlobalSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public GlobalSettingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public GlobalSettingSwitchPreference(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return Settings.Global.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putBoolean(String key, boolean value) {
|
||||
Settings.Global.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String key, boolean defaultValue) {
|
||||
return Settings.Global.getInt(getContext().getContentResolver(),
|
||||
key, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageGlobalSettingListPreference extends SelfRemovingListPreference {
|
||||
|
||||
public LineageGlobalSettingListPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageGlobalSettingListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public int getIntValue(int defValue) {
|
||||
return getValue() == null ? defValue : Integer.valueOf(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.Global.getString(getContext().getContentResolver(),
|
||||
getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putString(String key, String value) {
|
||||
LineageSettings.Global.putString(getContext().getContentResolver(), key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String key, String defaultValue) {
|
||||
return LineageSettings.Global.getString(getContext().getContentResolver(),
|
||||
key, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageGlobalSettingMainSwitchPreference extends MainSwitchPreference {
|
||||
|
||||
public LineageGlobalSettingMainSwitchPreference(Context context, AttributeSet attrs,
|
||||
int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public LineageGlobalSettingMainSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public LineageGlobalSettingMainSwitchPreference(Context context) {
|
||||
super(context);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
LineageSettings.Global.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return LineageSettings.Global.getInt(getContext().getContentResolver(), key,
|
||||
defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageGlobalSettingSwitchPreference extends SelfRemovingSwitchPreference {
|
||||
|
||||
public LineageGlobalSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageGlobalSettingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LineageGlobalSettingSwitchPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.Global.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putBoolean(String key, boolean value) {
|
||||
LineageSettings.Global.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String key, boolean defaultValue) {
|
||||
return LineageSettings.Global.getInt(getContext().getContentResolver(),
|
||||
key, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
|
||||
public class LineageSecureSettingListPreference extends SelfRemovingListPreference {
|
||||
|
||||
public LineageSecureSettingListPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageSecureSettingListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public int getIntValue(int defValue) {
|
||||
return getValue() == null ? defValue : Integer.valueOf(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.Secure.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putString(String key, String value) {
|
||||
LineageSettings.Secure.putString(getContext().getContentResolver(), key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String key, String defaultValue) {
|
||||
return LineageSettings.Secure.getString(getContext().getContentResolver(),
|
||||
key, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageSecureSettingMainSwitchPreference extends MainSwitchPreference {
|
||||
|
||||
public LineageSecureSettingMainSwitchPreference(Context context, AttributeSet attrs,
|
||||
int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public LineageSecureSettingMainSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public LineageSecureSettingMainSwitchPreference(Context context) {
|
||||
super(context);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
LineageSettings.Secure.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return LineageSettings.Secure.getInt(getContext().getContentResolver(), key,
|
||||
defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageSecureSettingSwitchPreference extends SelfRemovingSwitchPreference {
|
||||
|
||||
public LineageSecureSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageSecureSettingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LineageSecureSettingSwitchPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.Secure.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putBoolean(String key, boolean value) {
|
||||
LineageSettings.Secure.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String key, boolean defaultValue) {
|
||||
return LineageSettings.Secure.getInt(getContext().getContentResolver(),
|
||||
key, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
|
||||
public class LineageSystemSettingDropDownPreference extends SelfRemovingDropDownPreference {
|
||||
public LineageSystemSettingDropDownPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageSystemSettingDropDownPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public int getIntValue(int defValue) {
|
||||
return getValue() == null ? defValue : Integer.valueOf(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.System.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putString(String key, String value) {
|
||||
LineageSettings.System.putString(getContext().getContentResolver(), key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String key, String defaultValue) {
|
||||
return LineageSettings.System.getString(getContext().getContentResolver(),
|
||||
key, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
|
||||
public class LineageSystemSettingListPreference extends SelfRemovingListPreference {
|
||||
public LineageSystemSettingListPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageSystemSettingListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public int getIntValue(int defValue) {
|
||||
return getValue() == null ? defValue : Integer.valueOf(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.System.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putString(String key, String value) {
|
||||
LineageSettings.System.putString(getContext().getContentResolver(), key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String key, String defaultValue) {
|
||||
return LineageSettings.System.getString(getContext().getContentResolver(),
|
||||
key, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageSystemSettingMainSwitchPreference extends MainSwitchPreference {
|
||||
|
||||
public LineageSystemSettingMainSwitchPreference(Context context, AttributeSet attrs,
|
||||
int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public LineageSystemSettingMainSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public LineageSystemSettingMainSwitchPreference(Context context) {
|
||||
super(context);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
LineageSettings.System.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return LineageSettings.System.getInt(getContext().getContentResolver(), key,
|
||||
defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class LineageSystemSettingSwitchPreference extends SelfRemovingSwitchPreference {
|
||||
|
||||
public LineageSystemSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LineageSystemSettingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LineageSystemSettingSwitchPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return LineageSettings.System.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putBoolean(String key, boolean value) {
|
||||
LineageSettings.System.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String key, boolean defaultValue) {
|
||||
return LineageSettings.System.getInt(getContext().getContentResolver(),
|
||||
key, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A RemotePreference is a view into preference logic which lives in another
|
||||
* process. The primary use case for this is at the platform level where
|
||||
* many applications may be contributing their preferences into the
|
||||
* Settings app.
|
||||
*
|
||||
* A RemotePreference appears as a PreferenceScreen and redirects to
|
||||
* the real application when clicked. The remote application can
|
||||
* send events back to the preference when data changes and the view
|
||||
* needs to be updated. See RemotePreferenceUpdater for a base class
|
||||
* to use on the application side which implements the listeners and
|
||||
* protocol.
|
||||
*
|
||||
* The interprocess communication is realized using BroadcastReceivers.
|
||||
* When the application wants to update the RemotePreference with
|
||||
* new data, it sends an ACTION_REFRESH_PREFERENCE with a particular
|
||||
* Uri. The RemotePreference listens while attached, and performs
|
||||
* an ordered broadcast with ACTION_UPDATE_PREFERENCE back to
|
||||
* the application, which is then returned to the preference after
|
||||
* being filled with new data.
|
||||
*
|
||||
* The external activity should include the META_REMOTE_RECEIVER
|
||||
* and (optionally) the META_REMOTE_KEY strings in it's metadata.
|
||||
* META_REMOTE_RECEIVER must contain the class name of the
|
||||
* RemotePreferenceUpdater which we should request updates from.
|
||||
* META_REMOTE_KEY must contain the key used by the preference
|
||||
* which should match on both sides.
|
||||
*/
|
||||
public class RemotePreference extends SelfRemovingPreference
|
||||
implements RemotePreferenceManager.OnRemoteUpdateListener {
|
||||
|
||||
private static final String TAG = RemotePreference.class.getSimpleName();
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);
|
||||
|
||||
public static final String ACTION_REFRESH_PREFERENCE =
|
||||
"lineageos.intent.action.REFRESH_PREFERENCE";
|
||||
|
||||
public static final String ACTION_UPDATE_PREFERENCE =
|
||||
"lineageos.intent.action.UPDATE_PREFERENCE";
|
||||
|
||||
public static final String META_REMOTE_RECEIVER =
|
||||
"org.lineageos.settings.summary.receiver";
|
||||
|
||||
public static final String META_REMOTE_KEY =
|
||||
"org.lineageos.settings.summary.key";
|
||||
|
||||
public static final String EXTRA_ENABLED = ":lineage:pref_enabled";
|
||||
public static final String EXTRA_KEY = ":lineage:pref_key";
|
||||
public static final String EXTRA_SUMMARY = ":lineage:pref_summary";
|
||||
|
||||
protected final Context mContext;
|
||||
|
||||
public RemotePreference(Context context, AttributeSet attrs,
|
||||
int defStyle, int defStyleRes) {
|
||||
super(context, attrs, defStyle, defStyleRes);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public RemotePreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
this(context, attrs, defStyle, 0);
|
||||
}
|
||||
|
||||
public RemotePreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, ConstraintsHelper.getAttr(context,
|
||||
androidx.preference.R.attr.preferenceStyle,
|
||||
android.R.attr.preferenceStyle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteUpdated(Bundle bundle) {
|
||||
if (DEBUG) Log.d(TAG, "onRemoteUpdated: " + bundle.toString());
|
||||
|
||||
if (bundle.containsKey(EXTRA_ENABLED)) {
|
||||
boolean available = bundle.getBoolean(EXTRA_ENABLED, true);
|
||||
if (available != isAvailable()) {
|
||||
setAvailable(available);
|
||||
}
|
||||
}
|
||||
if (isAvailable()) {
|
||||
setSummary(bundle.getString(EXTRA_SUMMARY));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttached() {
|
||||
super.onAttached();
|
||||
if (isAvailable()) {
|
||||
RemotePreferenceManager.get(mContext).attach(getKey(), this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetached() {
|
||||
super.onDetached();
|
||||
RemotePreferenceManager.get(mContext).detach(getKey(), this);
|
||||
}
|
||||
|
||||
protected String getRemoteKey(Bundle metaData) {
|
||||
String remoteKey = metaData.getString(META_REMOTE_KEY);
|
||||
return (remoteKey == null || !remoteKey.equals(getKey())) ? null : remoteKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getReceiverIntent() {
|
||||
final Intent i = getIntent();
|
||||
if (i == null) {
|
||||
Log.w(TAG, "No target intent specified in preference!");
|
||||
return null;
|
||||
}
|
||||
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(i,
|
||||
PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA,
|
||||
UserHandle.myUserId());
|
||||
|
||||
|
||||
if (results.size() == 0) {
|
||||
Log.w(TAG, "No activity found for: " + Objects.toString(i));
|
||||
}
|
||||
|
||||
for (ResolveInfo resolved : results) {
|
||||
ActivityInfo info = resolved.activityInfo;
|
||||
Log.d(TAG, "ResolveInfo " + Objects.toString(resolved));
|
||||
|
||||
Bundle meta = info.metaData;
|
||||
if (meta == null || !meta.containsKey(META_REMOTE_RECEIVER)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String receiverClass = meta.getString(META_REMOTE_RECEIVER);
|
||||
String receiverPackage = info.packageName;
|
||||
String remoteKey = getRemoteKey(meta);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "getReceiverIntent class=" + receiverClass +
|
||||
" package=" + receiverPackage + " key=" + remoteKey);
|
||||
|
||||
if (remoteKey == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Intent ri = new Intent(ACTION_UPDATE_PREFERENCE);
|
||||
ri.setComponent(new ComponentName(receiverPackage, receiverClass));
|
||||
ri.putExtra(EXTRA_KEY, remoteKey);
|
||||
return ri;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import lineageos.platform.Manifest;
|
||||
|
||||
import static lineageos.preference.RemotePreference.ACTION_REFRESH_PREFERENCE;
|
||||
import static lineageos.preference.RemotePreference.ACTION_UPDATE_PREFERENCE;
|
||||
import static lineageos.preference.RemotePreference.EXTRA_KEY;
|
||||
|
||||
/**
|
||||
* Manages attaching and detaching of RemotePreferences and optimizes callbacks
|
||||
* thru a single receiver on a separate thread.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class RemotePreferenceManager {
|
||||
|
||||
private static final String TAG = RemotePreferenceManager.class.getSimpleName();
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(
|
||||
RemotePreference.class.getSimpleName(), Log.VERBOSE);
|
||||
|
||||
private static RemotePreferenceManager sInstance;
|
||||
|
||||
private final Context mContext;
|
||||
private final Map<String, Intent> mCache = new ArrayMap<>();
|
||||
private final Map<String, Set<OnRemoteUpdateListener>> mCallbacks = new ArrayMap<>();
|
||||
|
||||
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private Handler mHandler;
|
||||
private HandlerThread mThread;
|
||||
|
||||
public interface OnRemoteUpdateListener {
|
||||
public Intent getReceiverIntent();
|
||||
|
||||
public void onRemoteUpdated(Bundle bundle);
|
||||
}
|
||||
|
||||
private RemotePreferenceManager(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public synchronized static RemotePreferenceManager get(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new RemotePreferenceManager(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void attach(String key, OnRemoteUpdateListener pref) {
|
||||
Intent i;
|
||||
synchronized (mCache) {
|
||||
i = mCache.get(key);
|
||||
if (i == null && !mCache.containsKey(key)) {
|
||||
i = pref.getReceiverIntent();
|
||||
mCache.put(key, i);
|
||||
}
|
||||
}
|
||||
synchronized (mCallbacks) {
|
||||
if (i != null) {
|
||||
Set<OnRemoteUpdateListener> cbs = mCallbacks.get(key);
|
||||
if (cbs == null) {
|
||||
cbs = new HashSet<>();
|
||||
mCallbacks.put(key, cbs);
|
||||
if (mCallbacks.size() == 1) {
|
||||
mThread = new HandlerThread("RemotePreference");
|
||||
mThread.start();
|
||||
mHandler = new Handler(mThread.getLooper());
|
||||
mContext.registerReceiver(mListener,
|
||||
new IntentFilter(ACTION_REFRESH_PREFERENCE),
|
||||
Manifest.permission.MANAGE_REMOTE_PREFERENCES, mHandler);
|
||||
}
|
||||
}
|
||||
cbs.add(pref);
|
||||
requestUpdate(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void detach(String key, OnRemoteUpdateListener pref) {
|
||||
synchronized (mCallbacks) {
|
||||
Set<OnRemoteUpdateListener> cbs = mCallbacks.get(key);
|
||||
if (cbs != null && cbs.remove(pref) && cbs.isEmpty()
|
||||
&& mCallbacks.remove(key) != null && mCallbacks.isEmpty()) {
|
||||
mContext.unregisterReceiver(mListener);
|
||||
if (mThread != null) {
|
||||
mThread.quit();
|
||||
mThread = null;
|
||||
}
|
||||
mHandler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requestUpdate(String key) {
|
||||
synchronized (mCache) {
|
||||
Intent i = mCache.get(key);
|
||||
if (i == null) {
|
||||
return;
|
||||
}
|
||||
mContext.sendOrderedBroadcastAsUser(i, UserHandle.CURRENT,
|
||||
Manifest.permission.MANAGE_REMOTE_PREFERENCES,
|
||||
mListener, mHandler, Activity.RESULT_OK, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mListener = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (DEBUG) Log.d(TAG, "onReceive: intent=" + Objects.toString(intent));
|
||||
|
||||
if (ACTION_REFRESH_PREFERENCE.equals(intent.getAction())) {
|
||||
final String key = intent.getStringExtra(EXTRA_KEY);
|
||||
synchronized (mCallbacks) {
|
||||
if (key != null && mCallbacks.containsKey(key)) {
|
||||
requestUpdate(key);
|
||||
}
|
||||
}
|
||||
} else if (ACTION_UPDATE_PREFERENCE.equals(intent.getAction())) {
|
||||
if (getAbortBroadcast()) {
|
||||
Log.e(TAG, "Broadcast aborted, code=" + getResultCode());
|
||||
return;
|
||||
}
|
||||
final Bundle bundle = getResultExtras(true);
|
||||
final String key = bundle.getString(EXTRA_KEY);
|
||||
synchronized (mCallbacks) {
|
||||
if (key != null && mCallbacks.containsKey(key)) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mCallbacks) {
|
||||
if (mCallbacks.containsKey(key)) {
|
||||
Set<OnRemoteUpdateListener> cbs = mCallbacks.get(key);
|
||||
if (cbs != null) {
|
||||
for (OnRemoteUpdateListener cb : cbs) {
|
||||
cb.onRemoteUpdated(bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import lineageos.platform.Manifest;
|
||||
|
||||
/**
|
||||
* Base class for remote summary providers.
|
||||
* <p>
|
||||
* When an application is hosting preferences which are served by a different process,
|
||||
* the former needs to stay updated with changes in order to display the correct
|
||||
* summary when the user returns to the latter.
|
||||
* <p>
|
||||
* This class implements a simple ordered broadcast mechanism where the application
|
||||
* running the RemotePreference sends an explicit broadcast to the host, who
|
||||
* fills out the extras in the result bundle and returns it to the caller.
|
||||
* <p>
|
||||
* A minimal implementation will override getSummary and return a summary
|
||||
* for the given key. Alternatively, fillResultExtras can be overridden
|
||||
* if additional data should be added to the result.
|
||||
*/
|
||||
public class RemotePreferenceUpdater extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = RemotePreferenceUpdater.class.getSimpleName();
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(
|
||||
RemotePreference.class.getSimpleName(), Log.VERBOSE);
|
||||
|
||||
private static Intent getTargetIntent(Context context, String key) {
|
||||
final Intent i = new Intent(RemotePreference.ACTION_REFRESH_PREFERENCE);
|
||||
i.putExtra(RemotePreference.EXTRA_KEY, key);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the updated summary for the given key
|
||||
*
|
||||
* @param key
|
||||
* @return the summary for the given key
|
||||
*/
|
||||
protected String getSummary(Context context, String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fill the bundle with the summary and any other data needed to update
|
||||
* the client.
|
||||
*
|
||||
* @param context
|
||||
* @param key
|
||||
* @param extras
|
||||
* @return true if successful
|
||||
*/
|
||||
protected boolean fillResultExtras(Context context, String key, Bundle extras) {
|
||||
extras.putString(RemotePreference.EXTRA_KEY, key);
|
||||
|
||||
final String summary = getSummary(context, key);
|
||||
if (summary == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
extras.putString(RemotePreference.EXTRA_SUMMARY, summary);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (isOrderedBroadcast() &&
|
||||
RemotePreference.ACTION_UPDATE_PREFERENCE.equals(intent.getAction())) {
|
||||
final String key = intent.getStringExtra(RemotePreference.EXTRA_KEY);
|
||||
if (DEBUG) Log.d(TAG, "onReceive key=" +key +
|
||||
" intent=" + Objects.toString(intent) +
|
||||
" extras=" + Objects.toString(intent.getExtras()));
|
||||
|
||||
if (key != null) {
|
||||
if (fillResultExtras(context, key, getResultExtras(true))) {
|
||||
setResultCode(Activity.RESULT_OK);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "onReceive result=" +
|
||||
Objects.toString(getResultExtras(true)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
abortBroadcast();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the RemotePreference that updated state is available. Call from
|
||||
* the fragment when necessary.
|
||||
*
|
||||
* @param context
|
||||
* @param key
|
||||
*/
|
||||
public static void notifyChanged(Context context, String key) {
|
||||
if (DEBUG) Log.d(TAG, "notifyChanged: key=" + key +
|
||||
" target=" + Objects.toString(getTargetIntent(context, key)));
|
||||
context.sendBroadcastAsUser(getTargetIntent(context, key),
|
||||
UserHandle.CURRENT, Manifest.permission.MANAGE_REMOTE_PREFERENCES);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
public class SecureSettingMainSwitchPreference extends MainSwitchPreference {
|
||||
|
||||
public SecureSettingMainSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SecureSettingMainSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SecureSettingMainSwitchPreference(Context context) {
|
||||
super(context, null);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
Settings.Secure.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return Settings.Secure.getInt(getContext().getContentResolver(), key,
|
||||
defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class SecureSettingSwitchPreference extends SelfRemovingSwitchPreference {
|
||||
|
||||
public SecureSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public SecureSettingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SecureSettingSwitchPreference(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return Settings.Secure.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putBoolean(String key, boolean value) {
|
||||
Settings.Secure.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String key, boolean defaultValue) {
|
||||
return Settings.Secure.getInt(getContext().getContentResolver(),
|
||||
key, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.DropDownPreference;
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
/**
|
||||
* A Preference which can automatically remove itself from the hierarchy
|
||||
* based on constraints set in XML.
|
||||
*/
|
||||
public abstract class SelfRemovingDropDownPreference extends DropDownPreference {
|
||||
|
||||
private final ConstraintsHelper mConstraints;
|
||||
|
||||
public SelfRemovingDropDownPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SelfRemovingDropDownPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SelfRemovingDropDownPreference(Context context) {
|
||||
super(context);
|
||||
mConstraints = new ConstraintsHelper(context, null, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttached() {
|
||||
super.onAttached();
|
||||
mConstraints.onAttached();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
mConstraints.onBindViewHolder(holder);
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
mConstraints.setAvailable(available);
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return mConstraints.isAvailable();
|
||||
}
|
||||
|
||||
protected abstract boolean isPersisted();
|
||||
protected abstract void putString(String key, String value);
|
||||
protected abstract String getString(String key, String defaultValue);
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
|
||||
final String value;
|
||||
if (!restorePersistedValue || !isPersisted()) {
|
||||
if (defaultValue == null) {
|
||||
return;
|
||||
}
|
||||
value = (String) defaultValue;
|
||||
if (shouldPersist()) {
|
||||
persistString(value);
|
||||
}
|
||||
} else {
|
||||
// Note: the default is not used because to have got here
|
||||
// isPersisted() must be true.
|
||||
value = getString(getKey(), null /* not used */);
|
||||
}
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putString(String key, String value) {
|
||||
SelfRemovingDropDownPreference.this.putString(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String key, String defaultValue) {
|
||||
return SelfRemovingDropDownPreference.this.getString(key, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
/**
|
||||
* A Preference which can automatically remove itself from the hierarchy
|
||||
* based on constraints set in XML.
|
||||
*/
|
||||
public abstract class SelfRemovingListPreference extends ListPreference {
|
||||
|
||||
private final ConstraintsHelper mConstraints;
|
||||
|
||||
public SelfRemovingListPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SelfRemovingListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SelfRemovingListPreference(Context context) {
|
||||
super(context);
|
||||
mConstraints = new ConstraintsHelper(context, null, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttached() {
|
||||
super.onAttached();
|
||||
mConstraints.onAttached();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
mConstraints.onBindViewHolder(holder);
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
mConstraints.setAvailable(available);
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return mConstraints.isAvailable();
|
||||
}
|
||||
|
||||
protected abstract boolean isPersisted();
|
||||
protected abstract void putString(String key, String value);
|
||||
protected abstract String getString(String key, String defaultValue);
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
|
||||
final String value;
|
||||
if (!restorePersistedValue || !isPersisted()) {
|
||||
if (defaultValue == null) {
|
||||
return;
|
||||
}
|
||||
value = (String) defaultValue;
|
||||
if (shouldPersist()) {
|
||||
persistString(value);
|
||||
}
|
||||
} else {
|
||||
// Note: the default is not used because to have got here
|
||||
// isPersisted() must be true.
|
||||
value = getString(getKey(), null /* not used */);
|
||||
}
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putString(String key, String value) {
|
||||
SelfRemovingListPreference.this.putString(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String key, String defaultValue) {
|
||||
return SelfRemovingListPreference.this.getString(key, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
/**
|
||||
* A Preference which can automatically remove itself from the hierarchy
|
||||
* based on constraints set in XML.
|
||||
*/
|
||||
public class SelfRemovingPreference extends Preference {
|
||||
|
||||
private final ConstraintsHelper mConstraints;
|
||||
|
||||
public SelfRemovingPreference(Context context, AttributeSet attrs,
|
||||
int defStyle, int defStyleRes) {
|
||||
super(context, attrs, defStyle, defStyleRes);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
}
|
||||
|
||||
public SelfRemovingPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
this(context, attrs, defStyle, 0);
|
||||
}
|
||||
|
||||
public SelfRemovingPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, ConstraintsHelper.getAttr(context,
|
||||
androidx.preference.R.attr.preferenceStyle,
|
||||
android.R.attr.preferenceStyle));
|
||||
}
|
||||
|
||||
public SelfRemovingPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttached() {
|
||||
super.onAttached();
|
||||
mConstraints.onAttached();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
mConstraints.onBindViewHolder(holder);
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
mConstraints.setAvailable(available);
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return mConstraints.isAvailable();
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
/**
|
||||
* A SwitchPreference which can automatically remove itself from the hierarchy
|
||||
* based on constraints set in XML.
|
||||
*/
|
||||
public abstract class SelfRemovingSwitchPreference extends SwitchPreference {
|
||||
|
||||
private final ConstraintsHelper mConstraints;
|
||||
|
||||
public SelfRemovingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SelfRemovingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mConstraints = new ConstraintsHelper(context, attrs, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SelfRemovingSwitchPreference(Context context) {
|
||||
super(context);
|
||||
mConstraints = new ConstraintsHelper(context, null, this);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttached() {
|
||||
super.onAttached();
|
||||
mConstraints.onAttached();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
mConstraints.onBindViewHolder(holder);
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
mConstraints.setAvailable(available);
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return mConstraints.isAvailable();
|
||||
}
|
||||
|
||||
protected abstract boolean isPersisted();
|
||||
protected abstract void putBoolean(String key, boolean value);
|
||||
protected abstract boolean getBoolean(String key, boolean defaultValue);
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
|
||||
final boolean checked;
|
||||
if (!restorePersistedValue || !isPersisted()) {
|
||||
if (defaultValue == null) {
|
||||
return;
|
||||
}
|
||||
checked = (boolean) defaultValue;
|
||||
if (shouldPersist()) {
|
||||
persistBoolean(checked);
|
||||
}
|
||||
} else {
|
||||
// Note: the default is not used because to have got here
|
||||
// isPersisted() must be true.
|
||||
checked = getBoolean(getKey(), false /* not used */);
|
||||
}
|
||||
setChecked(checked);
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
SelfRemovingSwitchPreference.this.putBoolean(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return SelfRemovingSwitchPreference.this.getBoolean(key, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import lineageos.providers.LineageSettings;
|
||||
|
||||
public class SettingsHelper {
|
||||
|
||||
private static final String SETTINGS_GLOBAL = Settings.Global.CONTENT_URI.toString();
|
||||
private static final String SETTINGS_SECURE = Settings.Secure.CONTENT_URI.toString();
|
||||
private static final String SETTINGS_SYSTEM = Settings.System.CONTENT_URI.toString();
|
||||
|
||||
private static final String LINEAGESETTINGS_GLOBAL = LineageSettings.Global.CONTENT_URI.toString();
|
||||
private static final String LINEAGESETTINGS_SECURE = LineageSettings.Secure.CONTENT_URI.toString();
|
||||
private static final String LINEAGESETTINGS_SYSTEM = LineageSettings.System.CONTENT_URI.toString();
|
||||
|
||||
private static SettingsHelper sInstance;
|
||||
|
||||
private final Context mContext;
|
||||
private final Observatory mObservatory;
|
||||
|
||||
private SettingsHelper(Context context) {
|
||||
mContext = context;
|
||||
mObservatory = new Observatory(context, new Handler());
|
||||
}
|
||||
|
||||
public static synchronized SettingsHelper get(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SettingsHelper(context);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public String getString(Uri settingsUri) {
|
||||
final String uri = settingsUri.toString();
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
|
||||
if (uri.startsWith(SETTINGS_SECURE)) {
|
||||
return Settings.Secure.getString(resolver, uri.substring(SETTINGS_SECURE.length()));
|
||||
} else if (uri.startsWith(SETTINGS_SYSTEM)) {
|
||||
return Settings.System.getString(resolver, uri.substring(SETTINGS_SYSTEM.length()));
|
||||
} else if (uri.startsWith(SETTINGS_GLOBAL)) {
|
||||
return Settings.Global.getString(resolver, uri.substring(SETTINGS_GLOBAL.length()));
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SECURE)) {
|
||||
return LineageSettings.Secure.getString(resolver, uri.substring(LINEAGESETTINGS_SECURE.length()));
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SYSTEM)) {
|
||||
return LineageSettings.System.getString(resolver, uri.substring(LINEAGESETTINGS_SYSTEM.length()));
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_GLOBAL)) {
|
||||
return LineageSettings.Global.getString(resolver, uri.substring(LINEAGESETTINGS_GLOBAL.length()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getInt(Uri settingsUri, int def) {
|
||||
final String uri = settingsUri.toString();
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
|
||||
if (uri.startsWith(SETTINGS_SECURE)) {
|
||||
return Settings.Secure.getInt(resolver, uri.substring(SETTINGS_SECURE.length()), def);
|
||||
} else if (uri.startsWith(SETTINGS_SYSTEM)) {
|
||||
return Settings.System.getInt(resolver, uri.substring(SETTINGS_SYSTEM.length()), def);
|
||||
} else if (uri.startsWith(SETTINGS_GLOBAL)) {
|
||||
return Settings.Global.getInt(resolver, uri.substring(SETTINGS_GLOBAL.length()), def);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SECURE)) {
|
||||
return LineageSettings.Secure.getInt(resolver, uri.substring(LINEAGESETTINGS_SECURE.length()), def);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SYSTEM)) {
|
||||
return LineageSettings.System.getInt(resolver, uri.substring(LINEAGESETTINGS_SYSTEM.length()), def);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_GLOBAL)) {
|
||||
return LineageSettings.Global.getInt(resolver, uri.substring(LINEAGESETTINGS_GLOBAL.length()), def);
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public boolean getBoolean(Uri settingsUri, boolean def) {
|
||||
int value = getInt(settingsUri, def ? 1 : 0);
|
||||
return value == 1;
|
||||
}
|
||||
|
||||
public void putString(Uri settingsUri, String value) {
|
||||
final String uri = settingsUri.toString();
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
|
||||
if (uri.startsWith(SETTINGS_SECURE)) {
|
||||
Settings.Secure.putString(resolver, uri.substring(SETTINGS_SECURE.length()), value);
|
||||
} else if (uri.startsWith(SETTINGS_SYSTEM)) {
|
||||
Settings.System.putString(resolver, uri.substring(SETTINGS_SYSTEM.length()), value);
|
||||
} else if (uri.startsWith(SETTINGS_GLOBAL)) {
|
||||
Settings.Global.putString(resolver, uri.substring(SETTINGS_GLOBAL.length()), value);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SECURE)) {
|
||||
LineageSettings.Secure.putString(resolver, uri.substring(LINEAGESETTINGS_SECURE.length()), value);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SYSTEM)) {
|
||||
LineageSettings.System.putString(resolver, uri.substring(LINEAGESETTINGS_SYSTEM.length()), value);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_GLOBAL)) {
|
||||
LineageSettings.Global.putString(resolver, uri.substring(LINEAGESETTINGS_GLOBAL.length()), value);
|
||||
}
|
||||
}
|
||||
|
||||
public void putInt(Uri settingsUri, int value) {
|
||||
final String uri = settingsUri.toString();
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
|
||||
if (uri.startsWith(SETTINGS_SECURE)) {
|
||||
Settings.Secure.putInt(resolver, uri.substring(SETTINGS_SECURE.length()), value);
|
||||
} else if (uri.startsWith(SETTINGS_SYSTEM)) {
|
||||
Settings.System.putInt(resolver, uri.substring(SETTINGS_SYSTEM.length()), value);
|
||||
} else if (uri.startsWith(SETTINGS_GLOBAL)) {
|
||||
Settings.Global.putInt(resolver, uri.substring(SETTINGS_GLOBAL.length()), value);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SECURE)) {
|
||||
LineageSettings.Secure.putInt(resolver, uri.substring(LINEAGESETTINGS_SECURE.length()), value);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_SYSTEM)) {
|
||||
LineageSettings.System.putInt(resolver, uri.substring(LINEAGESETTINGS_SYSTEM.length()), value);
|
||||
} else if (uri.startsWith(LINEAGESETTINGS_GLOBAL)) {
|
||||
LineageSettings.Global.putInt(resolver, uri.substring(LINEAGESETTINGS_GLOBAL.length()), value);
|
||||
}
|
||||
}
|
||||
|
||||
public void putBoolean(Uri settingsUri, boolean value) {
|
||||
putInt(settingsUri, value ? 1 : 0);
|
||||
}
|
||||
|
||||
public void startWatching(OnSettingsChangeListener listener, Uri... settingsUris) {
|
||||
mObservatory.register(listener, settingsUris);
|
||||
}
|
||||
|
||||
public void stopWatching(OnSettingsChangeListener listener) {
|
||||
mObservatory.unregister(listener);
|
||||
}
|
||||
|
||||
public interface OnSettingsChangeListener {
|
||||
public void onSettingsChanged(Uri settingsUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* A scalable ContentObserver that aggregates all listeners thru a single entrypoint.
|
||||
*/
|
||||
private static class Observatory extends ContentObserver {
|
||||
|
||||
private final Map<OnSettingsChangeListener, Set<Uri>> mTriggers = new ArrayMap<>();
|
||||
private final List<Uri> mRefs = new ArrayList<>();
|
||||
|
||||
private final Context mContext;
|
||||
private final ContentResolver mResolver;
|
||||
|
||||
public Observatory(Context context, Handler handler) {
|
||||
super(handler);
|
||||
mContext = context;
|
||||
mResolver = mContext.getContentResolver();
|
||||
}
|
||||
|
||||
public void register(OnSettingsChangeListener listener, Uri... contentUris) {
|
||||
synchronized (mRefs) {
|
||||
Set<Uri> uris = mTriggers.get(listener);
|
||||
if (uris == null) {
|
||||
uris = new ArraySet<Uri>();
|
||||
mTriggers.put(listener, uris);
|
||||
}
|
||||
for (Uri contentUri : contentUris) {
|
||||
uris.add(contentUri);
|
||||
if (!mRefs.contains(contentUri)) {
|
||||
mResolver.registerContentObserver(contentUri, false, this);
|
||||
listener.onSettingsChanged(null);
|
||||
}
|
||||
mRefs.add(contentUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(OnSettingsChangeListener listener) {
|
||||
synchronized (mRefs) {
|
||||
Set<Uri> uris = mTriggers.remove(listener);
|
||||
if (uris != null) {
|
||||
for (Uri uri : uris) {
|
||||
mRefs.remove(uri);
|
||||
}
|
||||
}
|
||||
if (mRefs.size() == 0) {
|
||||
mResolver.unregisterContentObserver(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
synchronized (mRefs) {
|
||||
super.onChange(selfChange, uri);
|
||||
|
||||
final Set<OnSettingsChangeListener> notify = new ArraySet<>();
|
||||
for (Map.Entry<OnSettingsChangeListener, Set<Uri>> entry : mTriggers.entrySet()) {
|
||||
if (entry.getValue().contains(uri)) {
|
||||
notify.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
for (OnSettingsChangeListener listener : notify) {
|
||||
listener.onSettingsChanged(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
public class SystemSettingMainSwitchPreference extends MainSwitchPreference {
|
||||
|
||||
public SystemSettingMainSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SystemSettingMainSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
public SystemSettingMainSwitchPreference(Context context) {
|
||||
super(context, null);
|
||||
setPreferenceDataStore(new DataStore());
|
||||
}
|
||||
|
||||
private class DataStore extends PreferenceDataStore {
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
Settings.System.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return Settings.System.getInt(getContext().getContentResolver(), key,
|
||||
defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The CyanogenMod Project
|
||||
* Copyright (C) 2018 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package lineageos.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class SystemSettingSwitchPreference extends SelfRemovingSwitchPreference {
|
||||
|
||||
public SystemSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public SystemSettingSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SystemSettingSwitchPreference(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPersisted() {
|
||||
return Settings.System.getString(getContext().getContentResolver(), getKey()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putBoolean(String key, boolean value) {
|
||||
Settings.System.putInt(getContext().getContentResolver(), key, value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String key, boolean defaultValue) {
|
||||
return Settings.System.getInt(getContext().getContentResolver(),
|
||||
key, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.lineageos.internal.lineageparts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import lineageos.preference.RemotePreference;
|
||||
|
||||
/**
|
||||
* A link to a remote preference screen which can be used with a minimum amount
|
||||
* of information. Supports summary updates asynchronously.
|
||||
*/
|
||||
public class LineagePartsPreference extends RemotePreference {
|
||||
|
||||
private static final String TAG = "LineagePartsPreference";
|
||||
|
||||
private final PartInfo mPart;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public LineagePartsPreference(Context context, AttributeSet attrs,
|
||||
int defStyle, int defStyleRes) {
|
||||
super(context, attrs, defStyle, defStyleRes);
|
||||
mContext = context;
|
||||
mPart = PartsList.get(context).getPartInfo(getKey());
|
||||
if (mPart == null) {
|
||||
throw new RuntimeException("Part not found: " + getKey());
|
||||
}
|
||||
|
||||
updatePreference();
|
||||
setIntent(mPart.getIntentForActivity());
|
||||
}
|
||||
|
||||
public LineagePartsPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
this(context, attrs, defStyle, 0);
|
||||
}
|
||||
|
||||
public LineagePartsPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, androidx.preference.R.attr.preferenceStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteUpdated(Bundle bundle) {
|
||||
if (bundle.containsKey(PartsList.EXTRA_PART)) {
|
||||
PartInfo update = bundle.getParcelable(PartsList.EXTRA_PART);
|
||||
if (update != null) {
|
||||
mPart.updateFrom(update);
|
||||
updatePreference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRemoteKey(Bundle metaData) {
|
||||
// remote key is the same as ours
|
||||
return getKey();
|
||||
}
|
||||
|
||||
private void updatePreference() {
|
||||
if (isAvailable() != mPart.isAvailable()) {
|
||||
setAvailable(mPart.isAvailable());
|
||||
}
|
||||
if (isAvailable()) {
|
||||
setTitle(mPart.getTitle());
|
||||
setSummary(mPart.getSummary());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.lineageos.internal.lineageparts;
|
||||
|
||||
parcelable PartInfo;
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.lineageos.internal.lineageparts;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import lineageos.os.Concierge;
|
||||
|
||||
public class PartInfo implements Parcelable {
|
||||
|
||||
private static final String TAG = PartInfo.class.getSimpleName();
|
||||
|
||||
private final String mName;
|
||||
|
||||
private String mTitle;
|
||||
|
||||
private String mSummary;
|
||||
|
||||
private String mFragmentClass;
|
||||
|
||||
private int mIconRes;
|
||||
|
||||
private boolean mAvailable = true;
|
||||
|
||||
/* for search provider */
|
||||
private int mXmlRes = 0;
|
||||
|
||||
public PartInfo(String name, String title, String summary) {
|
||||
mName = name;
|
||||
mTitle = title;
|
||||
mSummary = summary;
|
||||
}
|
||||
|
||||
public PartInfo(String name) {
|
||||
this(name, null, null);
|
||||
}
|
||||
|
||||
public PartInfo(Parcel parcel) {
|
||||
Concierge.ParcelInfo parcelInfo = Concierge.receiveParcel(parcel);
|
||||
int parcelableVersion = parcelInfo.getParcelVersion();
|
||||
|
||||
mName = parcel.readString();
|
||||
mTitle = parcel.readString();
|
||||
mSummary = parcel.readString();
|
||||
mFragmentClass = parcel.readString();
|
||||
mIconRes = parcel.readInt();
|
||||
mAvailable = parcel.readInt() == 1;
|
||||
mXmlRes = parcel.readInt();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public void setSummary(String summary) {
|
||||
mSummary = summary;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return mSummary;
|
||||
}
|
||||
|
||||
public String getFragmentClass() {
|
||||
return mFragmentClass;
|
||||
}
|
||||
|
||||
public void setFragmentClass(String fragmentClass) {
|
||||
mFragmentClass = fragmentClass;
|
||||
}
|
||||
|
||||
public int getIconRes() {
|
||||
return mIconRes;
|
||||
}
|
||||
|
||||
public void setIconRes(int iconRes) {
|
||||
mIconRes = iconRes;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return mAvailable;
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
mAvailable = available;
|
||||
}
|
||||
|
||||
public int getXmlRes() {
|
||||
return mXmlRes;
|
||||
}
|
||||
|
||||
public void setXmlRes(int xmlRes) {
|
||||
mXmlRes = xmlRes;
|
||||
}
|
||||
|
||||
public boolean updateFrom(PartInfo other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (other.equals(this)) {
|
||||
return false;
|
||||
}
|
||||
setTitle(other.getTitle());
|
||||
setSummary(other.getSummary());
|
||||
setFragmentClass(other.getFragmentClass());
|
||||
setIconRes(other.getIconRes());
|
||||
setAvailable(other.isAvailable());
|
||||
setXmlRes(other.getXmlRes());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PartInfo=[ name=%s title=%s summary=%s fragment=%s xmlRes=%x ]",
|
||||
mName, mTitle, mSummary, mFragmentClass, mXmlRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int i) {
|
||||
Concierge.ParcelInfo parcelInfo = Concierge.prepareParcel(out);
|
||||
|
||||
out.writeString(mName);
|
||||
out.writeString(mTitle);
|
||||
out.writeString(mSummary);
|
||||
out.writeString(mFragmentClass);
|
||||
out.writeInt(mIconRes);
|
||||
out.writeInt(mAvailable ? 1 : 0);
|
||||
out.writeInt(mXmlRes);
|
||||
parcelInfo.complete();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PartInfo o = (PartInfo) other;
|
||||
return Objects.equals(mName, o.mName) && Objects.equals(mTitle, o.mTitle) &&
|
||||
Objects.equals(mSummary, o.mSummary) && Objects.equals(mFragmentClass, o.mFragmentClass) &&
|
||||
Objects.equals(mIconRes, o.mIconRes) && Objects.equals(mAvailable, o.mAvailable) &&
|
||||
Objects.equals(mXmlRes, o.mXmlRes);
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return PartsList.PARTS_ACTION_PREFIX + "." + mName;
|
||||
}
|
||||
|
||||
public Intent getIntentForActivity() {
|
||||
Intent i = new Intent(getAction());
|
||||
i.setComponent(PartsList.LINEAGEPARTS_ACTIVITY);
|
||||
return i;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<PartInfo> CREATOR = new Parcelable.Creator<PartInfo>() {
|
||||
@Override
|
||||
public PartInfo createFromParcel(Parcel in) {
|
||||
return new PartInfo(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartInfo[] newArray(int size) {
|
||||
return new PartInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.lineageos.internal.lineageparts;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.util.XmlUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.android.internal.R.styleable.Preference;
|
||||
import static com.android.internal.R.styleable.Preference_fragment;
|
||||
import static com.android.internal.R.styleable.Preference_icon;
|
||||
import static com.android.internal.R.styleable.Preference_key;
|
||||
import static com.android.internal.R.styleable.Preference_summary;
|
||||
import static com.android.internal.R.styleable.Preference_title;
|
||||
import static lineageos.platform.R.styleable.lineage_Searchable;
|
||||
import static lineageos.platform.R.styleable.lineage_Searchable_xmlRes;
|
||||
|
||||
public class PartsList {
|
||||
|
||||
private static final String TAG = PartsList.class.getSimpleName();
|
||||
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);
|
||||
|
||||
public static final String EXTRA_PART = ":lineage:part";
|
||||
|
||||
public static final String LINEAGEPARTS_PACKAGE = "org.lineageos.lineageparts";
|
||||
|
||||
public static final ComponentName LINEAGEPARTS_ACTIVITY = new ComponentName(
|
||||
LINEAGEPARTS_PACKAGE, LINEAGEPARTS_PACKAGE + ".PartsActivity");
|
||||
|
||||
public static final String PARTS_ACTION_PREFIX = LINEAGEPARTS_PACKAGE + ".parts";
|
||||
|
||||
private final Map<String, PartInfo> mParts = new ArrayMap<>();
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private static PartsList sInstance;
|
||||
private static final Object sInstanceLock = new Object();
|
||||
|
||||
private PartsList(Context context) {
|
||||
mContext = context;
|
||||
loadParts();
|
||||
}
|
||||
|
||||
public static PartsList get(Context context) {
|
||||
synchronized (sInstanceLock) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new PartsList(context);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadParts() {
|
||||
synchronized (mParts) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
try {
|
||||
final Resources r = pm.getResourcesForApplication(LINEAGEPARTS_PACKAGE);
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
int resId = r.getIdentifier("parts_catalog", "xml", LINEAGEPARTS_PACKAGE);
|
||||
if (resId > 0) {
|
||||
loadPartsFromResourceLocked(r, resId, mParts);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// no lineageparts installed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getPartsList() {
|
||||
synchronized (mParts) {
|
||||
return mParts.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
public PartInfo getPartInfo(String key) {
|
||||
synchronized (mParts) {
|
||||
return mParts.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
public final PartInfo getPartInfoForClass(String clazz) {
|
||||
synchronized (mParts) {
|
||||
for (PartInfo info : mParts.values()) {
|
||||
if (info.getFragmentClass() != null && info.getFragmentClass().equals(clazz)) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPartsFromResourceLocked(Resources res, int resid,
|
||||
Map<String, PartInfo> target) {
|
||||
XmlResourceParser parser = null;
|
||||
|
||||
try {
|
||||
parser = res.getXml(resid);
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& type != XmlPullParser.START_TAG) {
|
||||
// Parse next until start tag is found
|
||||
}
|
||||
|
||||
String nodeName = parser.getName();
|
||||
if (!"parts-catalog".equals(nodeName)) {
|
||||
throw new RuntimeException(
|
||||
"XML document must start with <parts-catalog> tag; found "
|
||||
+ nodeName + " at " + parser.getPositionDescription());
|
||||
}
|
||||
|
||||
final int outerDepth = parser.getDepth();
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeName = parser.getName();
|
||||
if ("part".equals(nodeName)) {
|
||||
TypedArray sa = res.obtainAttributes(attrs, Preference);
|
||||
|
||||
String key = null;
|
||||
TypedValue tv = sa.peekValue(Preference_key);
|
||||
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
|
||||
if (tv.resourceId != 0) {
|
||||
key = res.getString(tv.resourceId);
|
||||
} else {
|
||||
key = String.valueOf(tv.string);
|
||||
}
|
||||
}
|
||||
if (key == null) {
|
||||
throw new RuntimeException("Attribute 'key' is required");
|
||||
}
|
||||
|
||||
final PartInfo info = new PartInfo(key);
|
||||
|
||||
tv = sa.peekValue(Preference_title);
|
||||
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
|
||||
if (tv.resourceId != 0) {
|
||||
info.setTitle(res.getString(tv.resourceId));
|
||||
} else {
|
||||
info.setTitle(String.valueOf(tv.string));
|
||||
}
|
||||
}
|
||||
|
||||
tv = sa.peekValue(Preference_summary);
|
||||
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
|
||||
if (tv.resourceId != 0) {
|
||||
info.setSummary(res.getString(tv.resourceId));
|
||||
} else {
|
||||
info.setSummary(String.valueOf(tv.string));
|
||||
}
|
||||
}
|
||||
|
||||
info.setFragmentClass(sa.getString(Preference_fragment));
|
||||
info.setIconRes(sa.getResourceId(Preference_icon, 0));
|
||||
|
||||
sa = res.obtainAttributes(attrs, lineage_Searchable);
|
||||
info.setXmlRes(sa.getResourceId(lineage_Searchable_xmlRes, 0));
|
||||
|
||||
sa.recycle();
|
||||
|
||||
target.put(key, info);
|
||||
|
||||
} else {
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
}
|
||||
}
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException("Error parsing catalog", e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error parsing catalog", e);
|
||||
} finally {
|
||||
if (parser != null) parser.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user