blob: e6149958967e835b57e62e3a88ac55c4049daa72 [file] [log] [blame]
/*
* 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 cyanogenmod.preference;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import cyanogenmod.platform.R;
/**
* Helpers for checking if a device supports various features.
*/
public class ConstraintsHelper {
private static final String TAG = "Constraints";
private final Context mContext;
private final AttributeSet mAttrs;
private final Preference mPref;
private boolean mAvailable = true;
public ConstraintsHelper(Context context, AttributeSet attrs, Preference pref) {
mContext = context;
mAttrs = attrs;
mPref = pref;
mAvailable = checkConstraints();
}
public void setAvailable(boolean available) {
mAvailable = available;
}
public void applyConstraints() {
if (!mAvailable) {
final PreferenceGroup group = getParent(mPref);
group.removePreference(mPref);
if (group.getPreferenceCount() == 0) {
getParent(group).removePreference(group);
}
}
}
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 checkConstraints() {
if (mAttrs == null) {
return true;
}
TypedArray a = mContext.getResources().obtainAttributes(mAttrs,
R.styleable.cm_SelfRemovingPreference);
try {
// Check if the current user is an owner
boolean rOwner = a.getBoolean(R.styleable.cm_SelfRemovingPreference_requiresOwner, false);
if (rOwner && UserHandle.myUserId() != UserHandle.USER_OWNER) {
return false;
}
// Check if a specific package is installed
String rPackage = a.getString(R.styleable.cm_SelfRemovingPreference_requiresPackage);
if (rPackage != null && !isPackageInstalled(mContext, rPackage, false)) {
return false;
}
// Check if a system feature is available
String rFeature = a.getString(R.styleable.cm_SelfRemovingPreference_requiresFeature);
if (rFeature != null && !hasSystemFeature(mContext, rFeature)) {
return false;
}
// Check a boolean system property
String rProperty = a.getString(R.styleable.cm_SelfRemovingPreference_requiresProperty);
if (rProperty != null) {
String value = SystemProperties.get(rProperty);
if (value == null || !Boolean.parseBoolean(value)) {
return false;
}
}
// Check a config resource. This can be a bool or a string. A null string
// fails the constraint.
TypedValue tv = a.peekValue(R.styleable.cm_SelfRemovingPreference_requiresConfig);
if (tv != null) {
if (tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
if (mContext.getResources().getString(tv.resourceId) == null) {
return false;
}
}
} else if (tv.type == TypedValue.TYPE_INT_BOOLEAN) {
if (tv.resourceId != 0) {
if (tv.data == 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;
}
/**
* Does the device support Doze?
* @param context
* @return
*/
public static boolean isDozeAvailable(Context context) {
String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
if (TextUtils.isEmpty(name)) {
name = context.getResources().getString(
com.android.internal.R.string.config_dozeComponent);
}
return !TextUtils.isEmpty(name);
}
}