Add padlock to items in overflow menus and dropdown dialogs.

Bug: 26378442
Change-Id: I7b21ff8e0b95f6cda9f720f979f7c475244b340d
This commit is contained in:
Sudheer Shanka
2015-11-27 19:40:26 +00:00
parent 480c5ac083
commit 4bb4886fce
12 changed files with 566 additions and 133 deletions

View File

@@ -16,12 +16,12 @@
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="21dp"
android:height="24dp" android:height="21dp"
android:viewportWidth="24.0" android:viewportWidth="21.0"
android:viewportHeight="22.0" android:viewportHeight="21.0"
android:tint="?android:attr/colorAccent"> android:tint="?android:attr/colorAccent">
<path <path
android:fillColor="@android:color/white" android:fillColor="@android:color/white"
android:pathData="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v2H8.9V6zM18 20H6V10h12v10z" /> android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
</vector> </vector>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="wrap_content"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:ellipsize="marquee" />

View File

@@ -102,4 +102,6 @@
<!-- Accent color that matches the settings launcher icon --> <!-- Accent color that matches the settings launcher icon -->
<color name="icon_accent">#ffabffec</color> <color name="icon_accent">#ffabffec</color>
<color name="disabled_text_color">#66000000</color> <!-- 38% black -->
</resources> </resources>

View File

@@ -26,7 +26,7 @@
android:persistent="false" /> android:persistent="false" />
<!-- When device is locked --> <!-- When device is locked -->
<DropDownPreference <com.android.settings.RestrictedDropDownPreference
android:key="lock_screen_notifications" android:key="lock_screen_notifications"
android:title="@string/lock_screen_notifications_title" android:title="@string/lock_screen_notifications_title"
android:summary="%s" android:summary="%s"

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import com.android.settings.RestrictedLockUtils;
import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
public class RestrictedDropDownPreference extends DropDownPreference {
private Spinner mSpinner;
private final Drawable mRestrictedPadlock;
private final int mRestrictedPadlockPadding;
private List<RestrictedItem> mRestrictedItems = new ArrayList<>();
public RestrictedDropDownPreference(Context context) {
this(context, null);
}
public RestrictedDropDownPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
R.dimen.restricted_lock_icon_padding);
}
private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
if (position >= 0) {
String value = getEntryValues()[position].toString();
RestrictedItem item = getRestrictedItemForEntryValue(value);
if (item != null) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
item.enforcedAdmin);
mSpinner.setSelection(findIndexOfValue(getValue()));
} else if (!value.equals(getValue()) && callChangeListener(value)) {
setValue(value);
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// noop
}
};
@Override
protected ArrayAdapter createAdapter() {
return new RestrictedArrayItemAdapter(getContext());
}
@Override
public void setValue(String value) {
if (getRestrictedItemForEntryValue(value) != null) {
return;
}
super.setValue(value);
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
mSpinner = (Spinner) view.itemView.findViewById(R.id.spinner);
mSpinner.setOnItemSelectedListener(mItemSelectedListener);
}
private class RestrictedArrayItemAdapter extends ArrayAdapter<String> {
public RestrictedArrayItemAdapter(Context context) {
super(context, R.layout.spinner_dropdown_restricted_item);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
CharSequence entry = getItem(position);
boolean isEntryRestricted = isRestrictedForEntry(entry);
RestrictedLockUtils.setTextViewPadlock(getContext(), view, isEntryRestricted);
view.setEnabled(!isEntryRestricted);
return view;
}
}
private boolean isRestrictedForEntry(CharSequence entry) {
if (entry == null) {
return false;
}
for (RestrictedItem item : mRestrictedItems) {
if (entry.equals(item.entry)) {
return true;
}
}
return false;
}
private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
if (entryValue == null) {
return null;
}
for (RestrictedItem item : mRestrictedItems) {
if (entryValue.equals(item.entryValue)) {
return item;
}
}
return null;
}
public void addRestrictedItem(RestrictedItem item) {
mRestrictedItems.add(item);
}
public static class RestrictedItem {
public CharSequence entry;
public CharSequence entryValue;
public EnforcedAdmin enforcedAdmin;
public RestrictedItem(CharSequence entry, CharSequence entryValue,
EnforcedAdmin enforcedAdmin) {
this.entry = entry;
this.entryValue = entryValue;
this.enforcedAdmin = enforcedAdmin;
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.text.style.ImageSpan;
import java.lang.ref.WeakReference;
/**
* An extension of ImageSpan which adds a padding before the image.
*/
public class RestrictedLockImageSpan extends ImageSpan {
private Context mContext;
private final float mExtraPadding;
private final Drawable mRestrictedPadlock;
public RestrictedLockImageSpan(Context context) {
// we are overriding getDrawable, so passing null to super class here.
super((Drawable) null);
mContext = context;
mExtraPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.restricted_lock_icon_padding);
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
}
@Override
public Drawable getDrawable() {
return mRestrictedPadlock;
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
int bottom, Paint paint) {
Drawable drawable = getDrawable();
canvas.save();
// Add extra padding before the padlock.
float transX = x + mExtraPadding;
float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
canvas.translate(transX, transY);
drawable.draw(canvas);
canvas.restore();
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end,
Paint.FontMetricsInt fontMetrics) {
int size = super.getSize(paint, text, start, end, fontMetrics);
size += 2 * mExtraPadding;
return size;
}
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.Spanned;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.view.MenuItem;
import android.widget.TextView;
import java.util.List;
/**
* Utility class to host methods usable in adding a restricted padlock icon and showing admin
* support message dialog.
*/
public class RestrictedLockUtils {
/**
* @return drawables for displaying with settings that are locked by a device admin.
*/
public static Drawable getRestrictedPadlock(Context context) {
Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
final int iconSize = context.getResources().getDimensionPixelSize(
R.dimen.restricted_lock_icon_size);
restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
return restrictedPadlock;
}
/**
* Checks if a restriction is enforced on a user and returns the enforced admin and
* admin userId.
*
* @param userRestriction Restriction to check
* @param userId User which we need to check if restriction is enforced on.
* @return EnforcedAdmin Object containing the enforce admin and admin user details, or
* {@code null} If the restriction is not set. If the restriction is set by both device owner
* and profile owner, then the admin will be set to {@code null} and userId to
* {@link UserHandle#USER_NULL}.
*/
public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
String userRestriction, int userId) {
DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnAnyUser();
int deviceOwnerUserId = dpm.getDeviceOwnerUserId();
boolean enforcedByDeviceOwner = false;
if (deviceOwner != null && deviceOwnerUserId != UserHandle.USER_NULL) {
Bundle enforcedRestrictions = dpm.getUserRestrictions(deviceOwner, deviceOwnerUserId);
if (enforcedRestrictions != null
&& enforcedRestrictions.getBoolean(userRestriction, false)) {
enforcedByDeviceOwner = true;
}
}
ComponentName profileOwner = null;
boolean enforcedByProfileOwner = false;
if (userId != UserHandle.USER_NULL) {
profileOwner = dpm.getProfileOwnerAsUser(userId);
if (profileOwner != null) {
Bundle enforcedRestrictions = dpm.getUserRestrictions(profileOwner, userId);
if (enforcedRestrictions != null
&& enforcedRestrictions.getBoolean(userRestriction, false)) {
enforcedByProfileOwner = true;
}
}
}
if (!enforcedByDeviceOwner && !enforcedByProfileOwner) {
return null;
}
EnforcedAdmin admin = null;
if (enforcedByDeviceOwner && enforcedByProfileOwner) {
admin = new EnforcedAdmin();
} else if (enforcedByDeviceOwner) {
admin = new EnforcedAdmin(deviceOwner, deviceOwnerUserId);
} else {
admin = new EnforcedAdmin(profileOwner, userId);
}
return admin;
}
/**
* Checks if lock screen notification features are disabled by policy. This should be
* only used for keyguard notification features but not the keyguard features
* (e.g. KEYGUARD_DISABLE_FINGERPRINT) where a profile owner can set them on the parent user
* as it won't work for that case.
*
* @param keyguardNotificationFeatures Could be any of notification features that can be
* disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
* @return EnforcedAdmin Object containing the enforce admin and admin user details, or
* {@code null} If the notification features are not disabled. If the restriction is set by
* multiple admins, then the admin will be set to {@code null} and userId to
* {@link UserHandle#USER_NULL}.
*/
public static EnforcedAdmin checkIfKeyguardNotificationFeaturesDisabled(Context context,
int keyguardNotificationFeatures) {
final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
boolean isDisabledByMultipleAdmins = false;
ComponentName adminComponent = null;
List<ComponentName> admins = dpm.getActiveAdmins();
int disabledKeyguardFeatures;
for (ComponentName admin : admins) {
disabledKeyguardFeatures = dpm.getKeyguardDisabledFeatures(admin);
if ((disabledKeyguardFeatures & keyguardNotificationFeatures) != 0) {
if (adminComponent == null) {
adminComponent = admin;
} else {
isDisabledByMultipleAdmins = true;
break;
}
}
}
EnforcedAdmin enforcedAdmin = null;
if (adminComponent != null) {
if (!isDisabledByMultipleAdmins) {
enforcedAdmin = new EnforcedAdmin(adminComponent, UserHandle.myUserId());
} else {
enforcedAdmin = new EnforcedAdmin();
}
}
return enforcedAdmin;
}
/**
* Set the menu item as disabled by admin by adding a restricted padlock at the end of the
* text and set the click listener which will send an intent to show the admin support details
* dialog.
*/
public static void setMenuItemAsDisabledByAdmin(final Context context,
final MenuItem item, final EnforcedAdmin admin) {
SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle());
removeExistingRestrictedSpans(sb);
final int disabledColor = context.getColor(R.color.disabled_text_color);
sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ImageSpan image = new RestrictedLockImageSpan(context);
sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
item.setTitle(sb);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
sendShowAdminSupportDetailsIntent(context, admin);
return true;
}
});
}
private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) {
final int length = sb.length();
RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length,
RestrictedLockImageSpan.class);
for (ImageSpan span : imageSpans) {
sb.removeSpan(span);
}
ForegroundColorSpan[] colorSpans = sb.getSpans(0, length, ForegroundColorSpan.class);
for (ForegroundColorSpan span : colorSpans) {
sb.removeSpan(span);
}
}
/**
* Send the intent to trigger the {@link android.settings.ShowAdminSupportDetailsDialog}.
*/
public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
Intent intent = new Intent(context, ShowAdminSupportDetailsDialog.class);
int adminUserId = UserHandle.myUserId();
if (admin != null) {
if (admin.component != null) {
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
}
if (admin.userId != UserHandle.USER_NULL) {
adminUserId = admin.userId;
}
intent.putExtra(Intent.EXTRA_USER_ID, adminUserId);
}
context.startActivityAsUser(intent, new UserHandle(adminUserId));
}
public static void setTextViewPadlock(Context context,
TextView textView, boolean showPadlock) {
final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText());
removeExistingRestrictedSpans(sb);
if (showPadlock) {
final ImageSpan image = new RestrictedLockImageSpan(context);
sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
textView.setText(sb);
}
public static class EnforcedAdmin {
public ComponentName component = null;
public int userId = UserHandle.USER_NULL;
public EnforcedAdmin(ComponentName component, int userId) {
this.component = component;
this.userId = userId;
}
public EnforcedAdmin() {}
}
}

View File

@@ -16,7 +16,6 @@
package com.android.settings; package com.android.settings;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.os.UserHandle; import android.os.UserHandle;
import android.support.v4.content.res.TypedArrayUtils; import android.support.v4.content.res.TypedArrayUtils;
@@ -25,6 +24,8 @@ import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceViewHolder; import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet; import android.util.AttributeSet;
import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
/** /**
* Preference class that supports being disabled by a user restriction * Preference class that supports being disabled by a user restriction
* set by a device admin. * set by a device admin.
@@ -78,12 +79,8 @@ public class RestrictedPreference extends Preference {
mHelper.checkRestrictionAndSetDisabled(userRestriction, userId); mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
} }
public void setDisabledByAdmin(boolean disabled) { public void setDisabledByAdmin(EnforcedAdmin admin) {
mHelper.setDisabledByAdmin(disabled, null, UserHandle.USER_NULL); if (mHelper.setDisabledByAdmin(admin)) {
}
public void setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
if (mHelper.setDisabledByAdmin(disabled, admin, userId)) {
notifyChanged(); notifyChanged();
} }
} }

View File

@@ -16,36 +16,33 @@
package com.android.settings; package com.android.settings;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder; import android.support.v7.preference.PreferenceViewHolder;
import android.text.Spanned;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
/** /**
* Helper class for managing settings preferences that can be disabled * Helper class for managing settings preferences that can be disabled
* by device admins via user restrictions. * by device admins via user restrictions.
* */
**/
public class RestrictedPreferenceHelper { public class RestrictedPreferenceHelper {
private final Context mContext; private final Context mContext;
private final Preference mPreference; private final Preference mPreference;
private final Drawable mRestrictedPadlock; private final Drawable mRestrictedPadlock;
private final int mRestrictedPadlockPadding; private final int mRestrictedPadlockPadding;
private final DevicePolicyManager mDevicePolicyManager;
private boolean mDisabledByAdmin; private boolean mDisabledByAdmin;
private ComponentName mEnforcedAdmin; private EnforcedAdmin mEnforcedAdmin;
private int mUserId = UserHandle.USER_NULL;
private String mAttrUserRestriction = null; private String mAttrUserRestriction = null;
RestrictedPreferenceHelper(Context context, Preference preference, RestrictedPreferenceHelper(Context context, Preference preference,
@@ -53,13 +50,10 @@ public class RestrictedPreferenceHelper {
mContext = context; mContext = context;
mPreference = preference; mPreference = preference;
mRestrictedPadlock = getRestrictedPadlock(mContext); mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize( mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.restricted_lock_icon_padding); R.dimen.restricted_lock_icon_padding);
mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
mAttrUserRestriction = attrs.getAttributeValue( mAttrUserRestriction = attrs.getAttributeValue(
R.styleable.RestrictedPreference_userRestriction); R.styleable.RestrictedPreference_userRestriction);
final TypedArray attributes = context.obtainStyledAttributes(attrs, final TypedArray attributes = context.obtainStyledAttributes(attrs,
@@ -83,12 +77,9 @@ public class RestrictedPreferenceHelper {
public void onBindViewHolder(PreferenceViewHolder holder) { public void onBindViewHolder(PreferenceViewHolder holder) {
final TextView titleView = (TextView) holder.findViewById(android.R.id.title); final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
if (titleView != null) { if (titleView != null) {
RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
if (mDisabledByAdmin) { if (mDisabledByAdmin) {
titleView.setCompoundDrawablesRelative(null, null, mRestrictedPadlock, null);
titleView.setCompoundDrawablePadding(mRestrictedPadlockPadding);
holder.itemView.setEnabled(true); holder.itemView.setEnabled(true);
} else {
titleView.setCompoundDrawablesRelative(null, null, null, null);
} }
} }
} }
@@ -100,14 +91,7 @@ public class RestrictedPreferenceHelper {
*/ */
public boolean performClick() { public boolean performClick() {
if (mDisabledByAdmin) { if (mDisabledByAdmin) {
Intent intent = new Intent(mContext, ShowAdminSupportDetailsDialog.class); RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin);
if (mEnforcedAdmin != null) {
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mEnforcedAdmin);
}
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
mContext.startActivity(intent);
return true; return true;
} }
return false; return false;
@@ -129,57 +113,23 @@ public class RestrictedPreferenceHelper {
* @param userId user to check the restriction for. * @param userId user to check the restriction for.
*/ */
public void checkRestrictionAndSetDisabled(String userRestriction, int userId) { public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
ComponentName deviceOwner = mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser(); EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
int deviceOwnerUserId = mDevicePolicyManager.getDeviceOwnerUserId(); userRestriction, userId);
boolean enforcedByDeviceOwner = false; setDisabledByAdmin(admin);
if (deviceOwner != null && deviceOwnerUserId != UserHandle.USER_NULL) {
enforcedByDeviceOwner = isEnforcedByAdmin(
deviceOwner, userRestriction, deviceOwnerUserId);
}
ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
boolean enforcedByProfileOwner = false;
if (profileOwner != null && userId != UserHandle.USER_NULL) {
enforcedByProfileOwner = isEnforcedByAdmin(
profileOwner, userRestriction, userId);
}
if (!enforcedByDeviceOwner && !enforcedByProfileOwner) {
setDisabledByAdmin(false, null, UserHandle.USER_NULL);
return;
}
if (enforcedByDeviceOwner && enforcedByProfileOwner) {
setDisabledByAdmin(true, null, UserHandle.USER_NULL);
} else if (enforcedByDeviceOwner) {
setDisabledByAdmin(true, deviceOwner, deviceOwnerUserId);
} else {
setDisabledByAdmin(true, profileOwner, userId);
}
}
private boolean isEnforcedByAdmin(ComponentName admin, String userRestriction, int userId) {
Bundle enforcedRestrictions = mDevicePolicyManager.getUserRestrictions(admin, userId);
if (enforcedRestrictions != null
&& enforcedRestrictions.getBoolean(userRestriction, false)) {
return true;
}
return false;
} }
/** /**
* Disable this preference. * Disable this preference based on the enforce admin.
* *
* @param disabled true if preference should be disabled. * @param EnforcedAdmin Details of the admin who enforced the restriction. If it
* @param admin Device admin that disabled the preference. * is {@code null}, then this preference will be enabled. Otherwise, it will be disabled.
* @param userId userId the device admin is installed for.
* @return true if the disabled state was changed. * @return true if the disabled state was changed.
*/ */
public boolean setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) { public boolean setDisabledByAdmin(EnforcedAdmin admin) {
final boolean disabled = (admin != null ? true : false);
mEnforcedAdmin = (disabled ? admin : null);
if (mDisabledByAdmin != disabled) { if (mDisabledByAdmin != disabled) {
mDisabledByAdmin = disabled; mDisabledByAdmin = disabled;
mEnforcedAdmin = admin;
mUserId = userId;
mPreference.setEnabled(!disabled); mPreference.setEnabled(!disabled);
return true; return true;
} }
@@ -189,15 +139,4 @@ public class RestrictedPreferenceHelper {
public boolean isDisabledByAdmin() { public boolean isDisabledByAdmin() {
return mDisabledByAdmin; return mDisabledByAdmin;
} }
/**
* @return drawables for displaying with settings that are locked by a device admin.
*/
public static Drawable getRestrictedPadlock(Context context) {
Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
final int iconSize = context.getResources().getDimensionPixelSize(
R.dimen.restricted_lock_icon_size);
restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
return restrictedPadlock;
}
} }

View File

@@ -16,7 +16,6 @@
package com.android.settings; package com.android.settings;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.os.UserHandle; import android.os.UserHandle;
import android.support.v4.content.res.TypedArrayUtils; import android.support.v4.content.res.TypedArrayUtils;
@@ -25,6 +24,8 @@ import android.support.v7.preference.PreferenceViewHolder;
import android.support.v14.preference.SwitchPreference; import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet; import android.util.AttributeSet;
import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
/** /**
* Version of SwitchPreference that can be disabled by a device admin * Version of SwitchPreference that can be disabled by a device admin
* using a user restriction. * using a user restriction.
@@ -78,12 +79,8 @@ public class RestrictedSwitchPreference extends SwitchPreference {
mHelper.checkRestrictionAndSetDisabled(userRestriction, userId); mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
} }
public void setDisabledByAdmin(boolean disabled) { public void setDisabledByAdmin(EnforcedAdmin admin) {
mHelper.setDisabledByAdmin(disabled, null, UserHandle.USER_NULL); if (mHelper.setDisabledByAdmin(admin)) {
}
public void setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
if (mHelper.setDisabledByAdmin(disabled, admin, userId)) {
notifyChanged(); notifyChanged();
} }
} }

View File

@@ -28,11 +28,13 @@ import android.app.Dialog;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.content.SyncAdapterType; import android.content.SyncAdapterType;
import android.content.SyncInfo; import android.content.SyncInfo;
import android.content.SyncStatusInfo; import android.content.SyncStatusInfo;
import android.content.pm.ProviderInfo; import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.graphics.Color;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
@@ -52,6 +54,8 @@ import android.widget.TextView;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.RestrictedLockUtils;
import com.android.settings.ShowAdminSupportDetailsDialog;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
@@ -61,6 +65,8 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
public class AccountSyncSettings extends AccountPreferenceBase { public class AccountSyncSettings extends AccountPreferenceBase {
public static final String ACCOUNT_KEY = "account"; public static final String ACCOUNT_KEY = "account";
@@ -259,13 +265,17 @@ public class AccountSyncSettings extends AccountPreferenceBase {
MenuItem syncCancel = menu.add(0, MENU_SYNC_CANCEL_ID, 0, MenuItem syncCancel = menu.add(0, MENU_SYNC_CANCEL_ID, 0,
getString(R.string.sync_menu_sync_cancel)) getString(R.string.sync_menu_sync_cancel))
.setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel); .setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel);
final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
if (!um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle)) {
MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0, MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
getString(R.string.remove_account_label)) getString(R.string.remove_account_label))
.setIcon(R.drawable.ic_menu_delete); .setIcon(R.drawable.ic_menu_delete);
removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER | removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
MenuItem.SHOW_AS_ACTION_WITH_TEXT); MenuItem.SHOW_AS_ACTION_WITH_TEXT);
final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
getPrefContext(), UserManager.DISALLOW_MODIFY_ACCOUNTS,
mUserHandle.getIdentifier());
if (admin != null) {
RestrictedLockUtils.setMenuItemAsDisabledByAdmin(getPrefContext(),
removeAccount, admin);
} }
syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER | syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
MenuItem.SHOW_AS_ACTION_WITH_TEXT); MenuItem.SHOW_AS_ACTION_WITH_TEXT);

View File

@@ -19,9 +19,11 @@ package com.android.settings.notification;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.settings.InstrumentedFragment; import com.android.settings.InstrumentedFragment;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.RestrictedDropDownPreference;
import com.android.settings.RestrictedDropDownPreference.RestrictedItem;
import com.android.settings.RestrictedLockUtils;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver; import android.database.ContentObserver;
@@ -30,13 +32,18 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener; import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.TwoStatePreference; import android.support.v7.preference.TwoStatePreference;
import android.util.Log; import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
public class ConfigureNotificationSettings extends SettingsPreferenceFragment { public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
private static final String TAG = "ConfigNotiSettings"; private static final String TAG = "ConfigNotiSettings";
@@ -49,7 +56,7 @@ public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
private Context mContext; private Context mContext;
private TwoStatePreference mNotificationPulse; private TwoStatePreference mNotificationPulse;
private DropDownPreference mLockscreen; private RestrictedDropDownPreference mLockscreen;
private boolean mSecure; private boolean mSecure;
private int mLockscreenSelectedValue; private int mLockscreenSelectedValue;
@@ -124,28 +131,36 @@ public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
// === Lockscreen (public / private) notifications === // === Lockscreen (public / private) notifications ===
private void initLockscreenNotifications() { private void initLockscreenNotifications() {
mLockscreen = (DropDownPreference) getPreferenceScreen().findPreference( mLockscreen = (RestrictedDropDownPreference) getPreferenceScreen().findPreference(
KEY_LOCK_SCREEN_NOTIFICATIONS); KEY_LOCK_SCREEN_NOTIFICATIONS);
if (mLockscreen == null) { if (mLockscreen == null) {
Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS); Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS);
return; return;
} }
boolean isSecureNotificationsDisabled = isSecureNotificationsDisabled();
boolean isUnredactedNotificationsDisabled = isUnredactedNotificationsDisabled();
ArrayList<CharSequence> entries = new ArrayList<>(); ArrayList<CharSequence> entries = new ArrayList<>();
ArrayList<CharSequence> values = new ArrayList<>(); ArrayList<CharSequence> values = new ArrayList<>();
if (!isSecureNotificationsDisabled && !isUnredactedNotificationsDisabled) {
entries.add(getString(R.string.lock_screen_notifications_summary_show));
values.add(Integer.toString(R.string.lock_screen_notifications_summary_show));
}
if (mSecure && !isSecureNotificationsDisabled) {
entries.add(getString(R.string.lock_screen_notifications_summary_hide));
values.add(Integer.toString(R.string.lock_screen_notifications_summary_hide));
}
entries.add(getString(R.string.lock_screen_notifications_summary_disable)); entries.add(getString(R.string.lock_screen_notifications_summary_disable));
values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable)); values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));
String summaryShowEntry = getString(R.string.lock_screen_notifications_summary_show);
String summaryShowEntryValue = Integer.toString(
R.string.lock_screen_notifications_summary_show);
entries.add(summaryShowEntry);
values.add(summaryShowEntryValue);
setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
if (mSecure) {
String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
String summaryHideEntryValue = Integer.toString(
R.string.lock_screen_notifications_summary_hide);
entries.add(summaryHideEntry);
values.add(summaryHideEntryValue);
setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
}
mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()])); mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()])); mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
updateLockscreenNotifications(); updateLockscreenNotifications();
@@ -174,18 +189,14 @@ public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
} }
} }
private boolean isSecureNotificationsDisabled() { private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
final DevicePolicyManager dpm = CharSequence entryValue, int keyguardNotificationFeatures) {
(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardNotificationFeaturesDisabled(
return dpm != null && (dpm.getKeyguardDisabledFeatures(null) mContext, keyguardNotificationFeatures);
& DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0; if (admin != null) {
RestrictedItem item = new RestrictedItem(entry, entryValue, admin);
mLockscreen.addRestrictedItem(item);
} }
private boolean isUnredactedNotificationsDisabled() {
final DevicePolicyManager dpm =
(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
& DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
} }
private void updateLockscreenNotifications() { private void updateLockscreenNotifications() {