Snap for 6549967 from 649e54d414 to mainline-release

Change-Id: Ieb3f025f4f9078c25c7508e207971601d3f16fe5
This commit is contained in:
android-build-team Robot
2020-06-02 07:09:40 +00:00
34 changed files with 786 additions and 564 deletions

View File

@@ -25,7 +25,6 @@
android:layout_width="56dip"
android:layout_height="56dip"
android:layout_gravity="bottom"
android:layout_marginEnd="6dp"
android:contentDescription="@string/user_image_photo_selector"
android:background="@*android:drawable/spinner_background_holo_dark"
android:scaleType="fitCenter"/>

View File

@@ -69,10 +69,10 @@
<Button
android:id="@+id/nfc_how_it_works_button"
android:background="?android:attr/selectableItemBackground"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginRight="20dp"
android:layout_marginEnd="20dp"
android:text="@string/nfc_how_it_works_got_it"
android:textSize="14sp"
android:textColor="#263238"

View File

@@ -32,7 +32,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@*android:dimen/status_bar_icon_size"
android:paddingBottom="6dp">
android:gravity="center_vertical"
android:layout_marginBottom="6dp">
<ImageView
android:id="@+id/icon"
@@ -62,11 +63,10 @@
<ImageView
android:id="@+id/alerted_icon"
android:layout_width="@*android:dimen/status_bar_icon_size"
android:layout_height="@*android:dimen/status_bar_icon_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="6dp"
android:paddingTop="1dp"
android:scaleType="fitCenter"
android:visibility="gone"
android:tint="?android:attr/textColorSecondary"
@@ -75,11 +75,9 @@
<ImageView
android:id="@+id/profile_badge"
android:layout_width="@*android:dimen/status_bar_icon_size"
android:layout_height="@*android:dimen/status_bar_icon_size"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:paddingTop="1dp"
android:scaleType="fitCenter"
android:contentDescription="@*android:string/notification_work_profile_content_description"
android:layout_toStartOf="@id/timestamp"
@@ -89,11 +87,7 @@
android:id="@+id/timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="@*android:dimen/status_bar_icon_size"
android:layout_alignBottom="@android:id/widget_frame"
android:layout_alignParentEnd="true"
android:layout_alignTop="@android:id/widget_frame"
android:layout_centerVertical="true"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.NotificationHistory.AppName"

View File

@@ -1,129 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:orientation="vertical"
android:focusable="true"
android:clickable="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/app_restrictions_pref"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:minWidth="@*android:dimen/preference_icon_minWidth"
android:orientation="horizontal">
<ImageView
android:id="@android:id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:minWidth="48dp"
android:scaleType="centerInside"
android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
tools:text="Richard"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:paddingBottom="3dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="13sp"
android:textColor="?android:attr/textColorSecondary"
android:focusable="false"
android:text="@string/user_summary_restricted_profile"
android:maxLines="4" />
</RelativeLayout>
<ImageView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingStart="16dip"
android:paddingEnd="16dip"
android:src="@drawable/ic_delete"
android:contentDescription="@string/user_delete_user_description"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
<LinearLayout
android:id="@+id/switch_pref"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:visibility="gone"
tools:visibility="visible"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground" >
<ImageView
android:id="@+id/switchIcon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:src="@drawable/ic_swap"
android:minWidth="48dp"
android:scaleType="centerInside"
android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
<TextView
android:id="@+id/switchTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
tools:text="Switch to Richard"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
</LinearLayout>
<View android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@color/divider_color" />
</LinearLayout>

View File

@@ -12046,6 +12046,9 @@
<!-- Power menu setting privacy show controls [CHAR LIMIT=NONE] -->
<string name="power_menu_privacy_show_controls">Show controls when locked</string>
<!-- Power menu setting privacy show cards [CHAR LIMIT=NONE] -->
<string name="power_menu_privacy_show_cards">Show cards when locked</string>
<!-- Power menu setting privacy hide all [CHAR LIMIT=NONE] -->
<string name="power_menu_privacy_hide">Hide cards and controls when locked</string>

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -344,11 +343,11 @@
</style>
<style name="TextAppearance.NotificationHistory.Title">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
</style>
<style name="TextAppearance.NotificationHistory.Text">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>

View File

@@ -25,6 +25,10 @@
android:key="enable_calling"
android:icon="@drawable/ic_phone"
android:title="@string/user_enable_calling_sms" />
<com.android.settingslib.RestrictedPreference
android:key="app_and_content_access"
android:icon="@drawable/ic_lock_closed"
android:title="@string/user_restrictions_title" />
<com.android.settingslib.RestrictedPreference
android:key="remove_user"
android:icon="@drawable/ic_delete"

View File

@@ -30,7 +30,6 @@ import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import com.android.settings.users.RestrictedProfileSettings;
import com.android.settingslib.license.LicenseHtmlLoaderCompat;
import java.io.File;
@@ -78,7 +77,7 @@ public class SettingsLicenseActivity extends FragmentActivity implements
@VisibleForTesting
Uri getUriFromGeneratedHtmlFile(File generatedHtmlFile) {
return FileProvider.getUriForFile(this, RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY,
return FileProvider.getUriForFile(this, Utils.FILE_PROVIDER_AUTHORITY,
generatedHtmlFile);
}

View File

@@ -116,6 +116,8 @@ public final class Utils extends com.android.settingslib.Utils {
private static final String TAG = "Settings";
public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
/**
* Set the preference's title to the matching activity's label.
*/

View File

@@ -17,6 +17,7 @@
package com.android.settings.gestures;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.text.TextUtils;
@@ -37,7 +38,9 @@ public class DeviceControlsPreferenceController extends GesturePreferenceControl
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
boolean available = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CONTROLS);
return available ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override

View File

@@ -17,6 +17,7 @@
package com.android.settings.gestures;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import com.android.settings.R;
@@ -37,15 +38,15 @@ public class PowerMenuPreferenceController extends BasePreferenceController {
@Override
public CharSequence getSummary() {
boolean controlsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
CONTROLS_ENABLED_SETTING, 1) == 1;
boolean cardsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
CARDS_ENABLED_SETTING, 0) == 1;
boolean cardsVisible = cardsEnabled && Settings.Secure.getInt(mContext.getContentResolver(),
CARDS_AVAILABLE_SETTING, 0) == 1;
if (controlsEnabled && cardsVisible) {
boolean controlsVisible = isControlsAvailable()
&& Settings.Secure.getInt(mContext.getContentResolver(),
CONTROLS_ENABLED_SETTING, 1) == 1;
boolean cardsVisible = isCardsAvailable()
&& Settings.Secure.getInt(mContext.getContentResolver(),
CARDS_ENABLED_SETTING, 0) == 1;
if (controlsVisible && cardsVisible) {
return mContext.getText(R.string.power_menu_cards_passes_device_controls);
} else if (controlsEnabled) {
} else if (controlsVisible) {
return mContext.getText(R.string.power_menu_device_controls);
} else if (cardsVisible) {
return mContext.getText(R.string.power_menu_cards_passes);
@@ -56,6 +57,15 @@ public class PowerMenuPreferenceController extends BasePreferenceController {
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
return isCardsAvailable() || isControlsAvailable() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
private boolean isControlsAvailable() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONTROLS);
}
private boolean isCardsAvailable() {
return Settings.Secure.getInt(mContext.getContentResolver(),
CARDS_AVAILABLE_SETTING, 0) == 1;
}
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.gestures;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -57,13 +58,20 @@ public class PowerMenuPrivacyPreferenceController extends TogglePreferenceContro
public CharSequence getSummary() {
boolean cardsAvailable = Settings.Secure.getInt(mContext.getContentResolver(),
CARDS_AVAILABLE_KEY, 0) != 0;
boolean controlsAvailable = isControlsAvailable();
final int res;
if (!isSecure()) {
res = R.string.power_menu_privacy_not_secure;
} else if (cardsAvailable) {
} else if (cardsAvailable && controlsAvailable) {
res = R.string.power_menu_privacy_show;
} else {
} else if (!cardsAvailable && controlsAvailable) {
res = R.string.power_menu_privacy_show_controls;
} else if (cardsAvailable) {
res = R.string.power_menu_privacy_show_cards;
} else {
// In this case, neither cards nor controls are available. This preference should not
// be accessible as the power menu setting is not accessible
return "";
}
return mContext.getText(res);
}
@@ -87,7 +95,7 @@ public class PowerMenuPrivacyPreferenceController extends TogglePreferenceContro
boolean cardsAvailable = Settings.Secure.getInt(resolver, CARDS_AVAILABLE_KEY, 0) != 0;
boolean cardsEnabled = Settings.Secure.getInt(resolver, CARDS_ENABLED_KEY, 0) != 0;
boolean controlsEnabled = Settings.Secure.getInt(resolver, CONTROLS_ENABLED_KEY, 1) != 0;
return (cardsAvailable && cardsEnabled) || controlsEnabled;
return (cardsAvailable && cardsEnabled) || (isControlsAvailable() && controlsEnabled);
}
private boolean isSecure() {
@@ -97,4 +105,8 @@ public class PowerMenuPrivacyPreferenceController extends TogglePreferenceContro
int userId = UserHandle.myUserId();
return utils.isSecure(userId);
}
private boolean isControlsAvailable() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONTROLS);
}
}

View File

@@ -73,6 +73,8 @@ public class BatteryFixSlice implements CustomSliceable {
UNIMPORTANT_BATTERY_TIPS = new ArrayMap<>();
UNIMPORTANT_BATTERY_TIPS.put(BatteryTip.TipType.SUMMARY,
Arrays.asList(BatteryTip.StateType.NEW, BatteryTip.StateType.HANDLED));
UNIMPORTANT_BATTERY_TIPS.put(BatteryTip.TipType.HIGH_DEVICE_USAGE,
Arrays.asList(BatteryTip.StateType.NEW, BatteryTip.StateType.HANDLED));
UNIMPORTANT_BATTERY_TIPS.put(BatteryTip.TipType.BATTERY_SAVER,
Arrays.asList(BatteryTip.StateType.HANDLED));
}

View File

@@ -106,7 +106,9 @@ public class MediaOutputSlice implements CustomSliceable {
final MediaDevice connectedDevice = worker.getCurrentConnectedMediaDevice();
if (devices.size() == 1) {
// Zero state
addRow(connectedDevice, connectedDevice, listBuilder);
for (MediaDevice device : devices) {
addRow(device, device, listBuilder);
}
listBuilder.addRow(getPairNewRow());
} else {
final boolean isTouched = worker.getIsTouched();

View File

@@ -168,6 +168,7 @@ public class EnabledNetworkModePreferenceController extends
private Context mContext;
private TelephonyManager mTelephonyManager;
private boolean mAllowed5gNetworkType;
private boolean mIsGlobalCdma;
private boolean mIs5gEntryDisplayed;
private boolean mShow4gForLTE;
@@ -205,6 +206,9 @@ public class EnabledNetworkModePreferenceController extends
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
final boolean isNrEnabledFromCarrierConfig = carrierConfig != null
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_NR_ENABLED_BOOL);
mAllowed5gNetworkType = checkSupportedRadioBitmask(
mTelephonyManager.getAllowedNetworkTypes(),
TelephonyManager.NETWORK_TYPE_BITMASK_NR);
mSupported5gRadioAccessFamily = isNrEnabledFromCarrierConfig
&& checkSupportedRadioBitmask(mTelephonyManager.getSupportedRadioAccessFamily(),
TelephonyManager.NETWORK_TYPE_BITMASK_NR);
@@ -568,7 +572,7 @@ public class EnabledNetworkModePreferenceController extends
}
/**
* Add 5G option. Only show the UI when device supported 5G.
* Add 5G option. Only show the UI when device supported 5G and allowed 5G.
*/
private void add5gEntry(int value) {
boolean isNRValue = value >= TelephonyManagerConstants.NETWORK_MODE_NR_ONLY;
@@ -581,13 +585,15 @@ public class EnabledNetworkModePreferenceController extends
mIs5gEntryDisplayed = false;
Log.d(LOG_TAG, "Hide 5G option. "
+ " supported5GRadioAccessFamily: " + mSupported5gRadioAccessFamily
+ " allowed5GNetworkType: " + mAllowed5gNetworkType
+ " isNRValue: " + isNRValue);
}
}
private void addGlobalEntry() {
Log.d(LOG_TAG, "addGlobalEntry. "
+ " supported5GRadioAccessFamily: " + mSupported5gRadioAccessFamily);
+ " supported5GRadioAccessFamily: " + mSupported5gRadioAccessFamily
+ " allowed5GNetworkType: " + mAllowed5gNetworkType);
mEntries.add(mContext.getString(R.string.network_global));
if (showNrList()) {
mEntriesValue.add(
@@ -599,7 +605,7 @@ public class EnabledNetworkModePreferenceController extends
}
private boolean showNrList() {
return mSupported5gRadioAccessFamily;
return mSupported5gRadioAccessFamily && mAllowed5gNetworkType;
}
/**

View File

@@ -32,6 +32,7 @@ import android.view.View;
import android.widget.ImageView;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
@@ -54,6 +55,13 @@ public class AppBubbleListPreferenceController extends AppConversationListPrefer
super(context, backend);
}
@Override
public void updateState(Preference preference) {
// loading convos is async; hide header until we know we have conversations to show
preference.setVisible(false);
super.updateState(preference);
}
@Override
public void onResume(NotificationBackend.AppRow appRow,
@Nullable NotificationChannel channel, @Nullable NotificationChannelGroup group,
@@ -134,6 +142,15 @@ public class AppBubbleListPreferenceController extends AppConversationListPrefer
return pref;
}
@Override
protected void populateList() {
super.populateList();
if (mPreference == null) {
return;
}
mPreference.setVisible(mPreference.getPreferenceCount() > 0);
}
/** Simple preference with a 'x' button at the end. */
@VisibleForTesting
public static class ConversationPreference extends Preference implements View.OnClickListener {

View File

@@ -116,7 +116,7 @@ public class AppConversationListPreferenceController extends NotificationPrefere
return R.string.conversations_category_title;
}
private void populateList() {
protected void populateList() {
if (mPreference == null) {
return;
}

View File

@@ -45,7 +45,7 @@ public class NotificationHistoryViewHolder extends RecyclerView.ViewHolder {
void setTitle(CharSequence title) {
mTitle.setText(title);
mTitle.setVisibility(title != null ? View.VISIBLE : View.GONE);
mTitle.setVisibility(title != null ? View.VISIBLE : View.INVISIBLE);
}
void setPostedTime(long postedTime) {

View File

@@ -97,15 +97,8 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
/** Key for extra passed in from calling fragment to indicate if this is a newly created user */
public static final String EXTRA_NEW_USER = "new_user";
/**
* Key for extra passed in from calling fragment to indicate if
* switch to user should be shown
*/
public static final String EXTRA_SHOW_SWITCH_USER = "enable_switch";
private boolean mFirstTime = true;
private boolean mNewUser;
protected boolean mShowSwitchUser;
private boolean mAppListChanged;
protected boolean mRestrictedProfile;
@@ -216,6 +209,12 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
}
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
init(icicle);
}
protected void init(Bundle icicle) {
if (icicle != null) {
mUser = new UserHandle(icicle.getInt(EXTRA_USER_ID));
@@ -226,7 +225,6 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
mUser = new UserHandle(args.getInt(EXTRA_USER_ID));
}
mNewUser = args.getBoolean(EXTRA_NEW_USER, false);
mShowSwitchUser = args.getBoolean(EXTRA_SHOW_SWITCH_USER, false);
}
}

View File

@@ -18,8 +18,10 @@ package com.android.settings.users;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -77,7 +79,9 @@ public class EditUserInfoController {
}
public void clear() {
mEditUserPhotoController.removeNewUserPhotoBitmapFile();
if (mEditUserPhotoController != null) {
mEditUserPhotoController.removeNewUserPhotoBitmapFile();
}
mEditUserInfoDialog = null;
mSavedPhoto = null;
}
@@ -116,7 +120,7 @@ public class EditUserInfoController {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mWaitingForActivityResult = false;
if (mEditUserInfoDialog != null) {
if (mEditUserPhotoController != null && mEditUserInfoDialog != null) {
mEditUserPhotoController.onActivityResult(requestCode, resultCode, data);
}
}
@@ -137,6 +141,14 @@ public class EditUserInfoController {
userNameView.setText(currentUserName);
final ImageView userPhotoView = (ImageView) content.findViewById(R.id.user_photo);
boolean canChangePhoto = mUserManager != null &&
canChangePhoto(activity, mUserManager.getUserInfo(user.getIdentifier()));
if (!canChangePhoto) {
// some users can't change their photos so we need to remove suggestive
// background from the photoView
userPhotoView.setBackground(null);
}
Drawable drawable = null;
if (mSavedPhoto != null) {
drawable = CircleFramedDrawable.getInstance(activity, mSavedPhoto);
@@ -144,7 +156,10 @@ public class EditUserInfoController {
drawable = currentUserIcon;
}
userPhotoView.setImageDrawable(drawable);
mEditUserPhotoController = createEditUserPhotoController(fragment, userPhotoView, drawable);
if (canChangePhoto) {
mEditUserPhotoController =
createEditUserPhotoController(fragment, userPhotoView, drawable);
}
mEditUserInfoDialog = new AlertDialog.Builder(activity)
.setTitle(title)
.setView(content)
@@ -158,21 +173,22 @@ public class EditUserInfoController {
if (!TextUtils.isEmpty(userName)) {
if (currentUserName == null
|| !userName.toString().equals(
currentUserName.toString())) {
currentUserName.toString())) {
if (callback != null) {
callback.onLabelChanged(mUser, userName.toString());
}
}
}
// Update the photo if changed.
Drawable drawable = mEditUserPhotoController.getNewUserPhotoDrawable();
if (drawable != null && !drawable.equals(currentUserIcon)) {
if (callback != null) {
if (mEditUserPhotoController != null) {
Drawable drawable =
mEditUserPhotoController.getNewUserPhotoDrawable();
if (drawable != null && !drawable.equals(currentUserIcon)) {
if (callback != null) {
callback.onPhotoChanged(mUser, drawable);
}
}
}
fragment.getActivity().removeDialog(
RestrictedProfileSettings.DIALOG_ID_EDIT_USER_INFO);
}
clear();
if (completeCallback != null) {
@@ -207,6 +223,13 @@ public class EditUserInfoController {
return mEditUserInfoDialog;
}
@VisibleForTesting
boolean canChangePhoto(Context context, UserInfo user) {
return PhotoCapabilityUtils.canCropPhoto(context) &&
(PhotoCapabilityUtils.canChoosePhoto(context)
|| PhotoCapabilityUtils.canTakePhoto(context));
}
@VisibleForTesting
EditUserPhotoController createEditUserPhotoController(Fragment fragment,
ImageView userPhotoView, Drawable drawable) {

View File

@@ -21,7 +21,6 @@ import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -52,6 +51,7 @@ import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.drawable.CircleFramedDrawable;
@@ -141,14 +141,14 @@ public class EditUserPhotoController {
}
private void showUpdatePhotoPopup() {
final boolean canTakePhoto = canTakePhoto();
final boolean canChoosePhoto = canChoosePhoto();
final Context context = mImageView.getContext();
final boolean canTakePhoto = PhotoCapabilityUtils.canTakePhoto(context);
final boolean canChoosePhoto = PhotoCapabilityUtils.canChoosePhoto(context);
if (!canTakePhoto && !canChoosePhoto) {
return;
}
final Context context = mImageView.getContext();
final List<EditUserPhotoController.RestrictedMenuItem> items = new ArrayList<>();
if (canTakePhoto) {
@@ -200,19 +200,6 @@ public class EditUserPhotoController {
listPopupWindow.show();
}
private boolean canTakePhoto() {
return mImageView.getContext().getPackageManager().queryIntentActivities(
new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
private boolean canChoosePhoto() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
return mImageView.getContext().getPackageManager().queryIntentActivities(
intent, 0).size() > 0;
}
private void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
appendOutputExtra(intent, mTakePictureUri);
@@ -369,8 +356,7 @@ public class EditUserPhotoController {
if (purge) {
fullPath.delete();
}
return FileProvider.getUriForFile(context,
RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY, fullPath);
return FileProvider.getUriForFile(context, Utils.FILE_PROVIDER_AUTHORITY, fullPath);
}
File saveNewUserPhotoBitmap() {

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2020 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.users;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.provider.MediaStore;
class PhotoCapabilityUtils {
/**
* Check if the current user can perform any activity for
* android.media.action.IMAGE_CAPTURE action.
*/
static boolean canTakePhoto(Context context) {
return context.getPackageManager().queryIntentActivities(
new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
/**
* Check if the current user can perform any activity for
* android.intent.action.GET_CONTENT action for images.
*/
static boolean canChoosePhoto(Context context) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
return context.getPackageManager().queryIntentActivities(intent, 0).size() > 0;
}
/**
* Check if the current user can perform any activity for
* com.android.camera.action.CROP action for images.
*/
static boolean canCropPhoto(Context context) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
return context.getPackageManager().queryIntentActivities(intent, 0).size() > 0;
}
}

View File

@@ -1,208 +0,0 @@
/*
* Copyright (C) 2013 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.users;
import android.app.ActivityManager;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.util.UserIcons;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.utils.ThreadUtils;
public class RestrictedProfileSettings extends AppRestrictionsFragment
implements EditUserInfoController.OnContentChangedCallback {
private static final String TAG = RestrictedProfileSettings.class.getSimpleName();
public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
static final int DIALOG_ID_EDIT_USER_INFO = 1;
private static final int DIALOG_CONFIRM_REMOVE = 2;
private View mHeaderView;
private ImageView mUserIconView;
private TextView mUserNameView;
private ImageView mDeleteButton;
private View mSwitchUserView;
private TextView mSwitchTitle;
private EditUserInfoController mEditUserInfoController =
new EditUserInfoController();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (icicle != null) {
mEditUserInfoController.onRestoreInstanceState(icicle);
}
init(icicle);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
mHeaderView = setPinnedHeaderView(R.layout.user_info_header);
mHeaderView.setOnClickListener(this);
mUserIconView = (ImageView) mHeaderView.findViewById(android.R.id.icon);
mUserNameView = (TextView) mHeaderView.findViewById(android.R.id.title);
mDeleteButton = (ImageView) mHeaderView.findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
mSwitchTitle = mHeaderView.findViewById(R.id.switchTitle);
mSwitchUserView = mHeaderView.findViewById(R.id.switch_pref);
mSwitchUserView.setOnClickListener(v -> switchUser());
// This is going to bind the preferences.
super.onActivityCreated(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mEditUserInfoController.onSaveInstanceState(outState);
}
@Override
public void onResume() {
super.onResume();
// Check if user still exists
UserInfo info = Utils.getExistingUser(mUserManager, mUser);
if (info == null) {
finishFragment();
} else {
((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
com.android.settingslib.Utils.getUserIcon(getActivity(), mUserManager, info));
boolean canSwitchUser =
mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
if (mShowSwitchUser && canSwitchUser) {
mSwitchUserView.setVisibility(View.VISIBLE);
mSwitchTitle.setText(getString(com.android.settingslib.R.string.user_switch_to_user,
info.name));
} else {
mSwitchUserView.setVisibility(View.GONE);
}
}
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
mEditUserInfoController.startingActivityForResult();
super.startActivityForResult(intent, requestCode);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onClick(View view) {
if (view == mHeaderView) {
showDialog(DIALOG_ID_EDIT_USER_INFO);
} else if (view == mDeleteButton) {
showDialog(DIALOG_CONFIRM_REMOVE);
} else {
super.onClick(view); // in AppRestrictionsFragment
}
}
@Override
public Dialog onCreateDialog(int dialogId) {
if (dialogId == DIALOG_ID_EDIT_USER_INFO) {
return mEditUserInfoController.createDialog(this, mUserIconView.getDrawable(),
mUserNameView.getText(), getString(R.string.profile_info_settings_title),
this, mUser, null);
} else if (dialogId == DIALOG_CONFIRM_REMOVE) {
Dialog dlg =
UserDialogs.createRemoveDialog(getActivity(), mUser.getIdentifier(),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
removeUser();
}
}
);
return dlg;
}
return null;
}
@Override
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
case DIALOG_ID_EDIT_USER_INFO:
return SettingsEnums.DIALOG_USER_EDIT;
case DIALOG_CONFIRM_REMOVE:
return SettingsEnums.DIALOG_USER_REMOVE;
default:
return 0;
}
}
private void removeUser() {
getView().post(new Runnable() {
public void run() {
mUserManager.removeUser(mUser.getIdentifier());
finishFragment();
}
});
}
private void switchUser() {
try {
ActivityManager.getService().switchUser(mUser.getIdentifier());
} catch (RemoteException re) {
Log.e(TAG, "Error while switching to other user.");
} finally {
finishFragment();
}
}
@Override
public void onPhotoChanged(UserHandle user, Drawable photo) {
mUserIconView.setImageDrawable(photo);
ThreadUtils.postOnBackgroundThread(new Runnable() {
@Override
public void run() {
mUserManager.setUserIcon(user.getIdentifier(), UserIcons.convertToBitmap(photo));
}
});
}
@Override
public void onLabelChanged(UserHandle user, CharSequence label) {
mUserNameView.setText(label);
mUserManager.setUserName(user.getIdentifier(), label.toString());
}
}

View File

@@ -36,6 +36,7 @@ import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -56,6 +57,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
private static final String KEY_SWITCH_USER = "switch_user";
private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
private static final String KEY_REMOVE_USER = "remove_user";
private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
/** Integer extra containing the userId to manage */
static final String EXTRA_USER_ID = "user_id";
@@ -69,6 +71,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
Preference mSwitchUserPref;
private SwitchPreference mPhonePref;
@VisibleForTesting
Preference mAppAndContentAccessPref;
@VisibleForTesting
Preference mRemoveUserPref;
@VisibleForTesting
@@ -109,6 +113,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
switchUser();
}
return true;
} else if (preference == mAppAndContentAccessPref) {
openAppAndContentAccessScreen(false);
}
return false;
}
@@ -170,11 +176,14 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
if (userId == USER_NULL) {
throw new IllegalStateException("Arguments to this fragment must contain the user id");
}
boolean isNewUser =
arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
mUserInfo = mUserManager.getUserInfo(userId);
mSwitchUserPref = findPreference(KEY_SWITCH_USER);
mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
mRemoveUserPref = findPreference(KEY_REMOVE_USER);
mAppAndContentAccessPref = findPreference(KEY_APP_AND_CONTENT_ACCESS);
mSwitchUserPref.setTitle(
context.getString(com.android.settingslib.R.string.user_switch_to_user,
@@ -184,16 +193,24 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
removePreference(KEY_ENABLE_TELEPHONY);
removePreference(KEY_REMOVE_USER);
removePreference(KEY_APP_AND_CONTENT_ACCESS);
} else {
if (!Utils.isVoiceCapable(context)) { // no telephony
removePreference(KEY_ENABLE_TELEPHONY);
}
if (!mUserInfo.isGuest()) {
mPhonePref.setChecked(!mUserManager.hasUserRestriction(
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
mRemoveUserPref.setTitle(R.string.user_remove_user);
if (mUserInfo.isRestricted()) {
removePreference(KEY_ENABLE_TELEPHONY);
if (isNewUser) {
// for newly created restricted users we should open the apps and content access
// screen to initialize the default restrictions
openAppAndContentAccessScreen(true);
}
} else {
removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
if (mUserInfo.isGuest()) {
// These are not for an existing user, just general Guest settings.
// Default title is for calling and SMS. Change to calling-only here
mPhonePref.setTitle(R.string.user_enable_calling);
@@ -201,6 +218,10 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mPhonePref.setChecked(
!mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
mRemoveUserPref.setTitle(R.string.user_exit_guest_title);
} else {
mPhonePref.setChecked(!mUserManager.hasUserRestriction(
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
mRemoveUserPref.setTitle(R.string.user_remove_user);
}
if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
@@ -209,6 +230,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mRemoveUserPref.setOnPreferenceClickListener(this);
mPhonePref.setOnPreferenceChangeListener(this);
mAppAndContentAccessPref.setOnPreferenceClickListener(this);
}
}
@@ -283,4 +305,20 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mUserManager.removeUser(mUserInfo.id);
finishFragment();
}
/**
* @param isNewUser indicates if a user was created recently, for new users
* AppRestrictionsFragment should set the default restrictions
*/
private void openAppAndContentAccessScreen(boolean isNewUser) {
Bundle extras = new Bundle();
extras.putInt(AppRestrictionsFragment.EXTRA_USER_ID, mUserInfo.id);
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, isNewUser);
new SubSettingLauncher(getContext())
.setDestination(AppRestrictionsFragment.class.getName())
.setArguments(extras)
.setTitleRes(R.string.user_restrictions_title)
.setSourceMetricsCategory(getMetricsCategory())
.launch();
}
}

View File

@@ -485,23 +485,13 @@ public class UserSettings extends SettingsPreferenceFragment
private void onManageUserClicked(int userId, boolean newUser) {
mAddingUser = false;
UserInfo userInfo = mUserManager.getUserInfo(userId);
if (userInfo.isRestricted() && mUserCaps.mIsAdmin) {
Bundle extras = new Bundle();
extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
extras.putBoolean(RestrictedProfileSettings.EXTRA_SHOW_SWITCH_USER, canSwitchUserNow());
new SubSettingLauncher(getContext())
.setDestination(RestrictedProfileSettings.class.getName())
.setArguments(extras)
.setTitleRes(R.string.user_restrictions_title)
.setSourceMetricsCategory(getMetricsCategory())
.launch();
} else if (userId == UserHandle.myUserId()) {
if (userId == UserHandle.myUserId()) {
// Jump to owner info panel
OwnerInfoSettings.show(this);
} else {
Bundle extras = new Bundle();
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
new SubSettingLauncher(getContext())
.setDestination(UserDetailsSettings.class.getName())
.setArguments(extras)
@@ -963,10 +953,10 @@ public class UserSettings extends SettingsPreferenceFragment
pref.setSummary(R.string.user_summary_restricted_not_set_up);
} else {
pref.setSummary(R.string.user_summary_not_set_up);
// Disallow setting up user which results in user switching when the
// restriction is set.
pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
}
// Disallow setting up user which results in user switching when the restriction is
// set.
pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
} else if (user.isRestricted()) {
pref.setSummary(R.string.user_summary_restricted_profile);
}
@@ -1137,17 +1127,14 @@ public class UserSettings extends SettingsPreferenceFragment
showDialog(DIALOG_CONFIRM_EXIT_GUEST);
return true;
}
// If this is a limited user, launch the user info settings instead of profile editor
if (mUserManager.isRestrictedProfile()) {
onManageUserClicked(UserHandle.myUserId(), false);
} else {
showDialog(DIALOG_USER_PROFILE_EDITOR);
}
showDialog(DIALOG_USER_PROFILE_EDITOR);
} else if (pref instanceof UserPreference) {
int userId = ((UserPreference) pref).getUserId();
// Get the latest status of the user
UserInfo user = mUserManager.getUserInfo(userId);
if (!user.isInitialized()) {
if (!user.isInitialized() && isSecondaryUser(user)) {
// for uninitialized secondary users we should show a prompt dialog before
// starting the setup
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_SETUP_USER, user.id, user.serialNumber));
} else {
@@ -1279,4 +1266,7 @@ public class UserSettings extends SettingsPreferenceFragment
}
};
private boolean isSecondaryUser(UserInfo user) {
return UserManager.USER_TYPE_FULL_SECONDARY.equals(user.userType);
}
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.gestures;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import com.android.settings.core.BasePreferenceController;
@@ -28,12 +29,15 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
public class DeviceControlsPreferenceControllerTest {
private Context mContext;
private DeviceControlsPreferenceController mController;
private ShadowPackageManager mShadowPackageManager;
private static final String KEY_GESTURE_PANEL = "gesture_device_controls";
private static final String ENABLED_SETTING =
@@ -42,6 +46,7 @@ public class DeviceControlsPreferenceControllerTest {
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new DeviceControlsPreferenceController(mContext, KEY_GESTURE_PANEL);
}
@@ -60,11 +65,21 @@ public class DeviceControlsPreferenceControllerTest {
}
@Test
public void getAvailabilityStatus_panelAvailable() {
public void getAvailabilityStatus_hasSystemFeature_panelAvailable() {
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, true);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_hasntSystemFeature_panelUnsupported() {
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, false);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
}
@Test
public void isSliceable_correctKey() {
final DeviceControlsPreferenceController controller =

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2020 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.gestures;
import static com.google.common.truth.Truth.assertThat;
import android.annotation.StringRes;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
import java.util.Arrays;
import java.util.Collection;
@RunWith(ParameterizedRobolectricTestRunner.class)
public class PowerMenuPreferenceControllerSummaryTest {
private static final String KEY_GESTURE_POWER_MENU = "gesture_power_menu";
private static final String CONTROLS_ENABLED = Settings.Secure.CONTROLS_ENABLED;
private static final String CONTROLS_FEATURE = PackageManager.FEATURE_CONTROLS;
private static final String CARDS_ENABLED = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
private static final String CARDS_AVAILABLE = Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
@ParameterizedRobolectricTestRunner.Parameters(
name = "ctrls available={0}, ctrls enabled={1}, cards available={2}, cards enabled={3}")
public static Collection data() {
return Arrays.asList(new Object[][]{
// controls available, controls enabled, cards available, cards enabled, summary
{false, false, false, false, R.string.power_menu_none},
{false, false, false, true, R.string.power_menu_none},
{false, false, true, false, R.string.power_menu_none},
{false, false, true, true, R.string.power_menu_cards_passes},
{false, true, false, false, R.string.power_menu_none},
{false, true, false, true, R.string.power_menu_none},
{false, true, true, false, R.string.power_menu_none},
{false, true, true, true, R.string.power_menu_cards_passes},
{true, false, false, false, R.string.power_menu_none},
{true, false, false, true, R.string.power_menu_none},
{true, false, true, false, R.string.power_menu_none},
{true, false, true, true, R.string.power_menu_cards_passes},
{true, true, false, false, R.string.power_menu_device_controls},
{true, true, false, true, R.string.power_menu_device_controls},
{true, true, true, false, R.string.power_menu_device_controls},
{true, true, true, true, R.string.power_menu_cards_passes_device_controls}
});
}
private Context mContext;
private PowerMenuPreferenceController mController;
private ShadowPackageManager mShadowPackageManager;
private boolean mControlsAvailable;
private boolean mControlsEnabled;
private boolean mCardsAvailable;
private boolean mCardsEnabled;
private @StringRes int mSummaryRes;
public PowerMenuPreferenceControllerSummaryTest(
boolean controlsAvailable,
boolean controlsEnabled,
boolean cardsAvailable,
boolean cardsEnabled,
@StringRes int summaryRes) {
mControlsAvailable = controlsAvailable;
mControlsEnabled = controlsEnabled;
mCardsAvailable = cardsAvailable;
mCardsEnabled = cardsEnabled;
mSummaryRes = summaryRes;
}
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new PowerMenuPreferenceController(mContext, KEY_GESTURE_POWER_MENU);
}
@Test
public void getSummary_possiblyAvailableAndEnabled() {
mShadowPackageManager.setSystemFeature(CONTROLS_FEATURE, mControlsAvailable);
ContentResolver cr = mContext.getContentResolver();
Settings.Secure.putInt(cr, CONTROLS_ENABLED, mControlsEnabled ? 1 : 0);
Settings.Secure.putInt(cr, CARDS_AVAILABLE, mCardsAvailable ? 1 : 0);
Settings.Secure.putInt(cr, CARDS_ENABLED, mCardsEnabled ? 1 : 0);
assertThat(mController.getSummary()).isEqualTo(mContext.getText(mSummaryRes));
}
}

View File

@@ -19,118 +19,71 @@ package com.android.settings.gestures;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
public class PowerMenuPreferenceControllerTest {
private Context mContext;
private PowerMenuPreferenceController mController;
private ShadowPackageManager mShadowPackageManager;
private static final String KEY_GESTURE_POWER_MENU = "gesture_power_menu";
private static final String CONTROLS_ENABLED = Settings.Secure.CONTROLS_ENABLED;
private static final String CONTROLS_FEATURE = PackageManager.FEATURE_CONTROLS;
private static final String CARDS_ENABLED = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
private static final String CARDS_AVAILABLE = Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new PowerMenuPreferenceController(mContext, KEY_GESTURE_POWER_MENU);
}
@Test
public void getAvailabilityStatus_available() {
public void getAvailabilityStatus_bothAvailable_available() {
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 1);
mShadowPackageManager.setSystemFeature(CONTROLS_FEATURE, true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getSummary_allDisabled() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 0);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_none));
}
@Test
public void getSummary_onlyControlsEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 0);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_device_controls));
}
@Test
public void getSummary_onlyCardsEnabled_notAvailable() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 0);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_none));
}
@Test
public void getSummary_cardsAvailable_notEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 0);
public void getAvailabilityStatus_onlyCardsAvailable_available() {
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 1);
mShadowPackageManager.setSystemFeature(CONTROLS_FEATURE, false);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_none));
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getSummary_allEnabled_cardsNotAvailable() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 1);
public void getAvailabilityStatus_onlyControlsAvailable_available() {
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 0);
mShadowPackageManager.setSystemFeature(CONTROLS_FEATURE, true);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_device_controls));
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getSummary_controlsEnabled_cardsDisabledAvailable() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 1);
public void getAvailabilityStatus_bothUnavailable_unavailable() {
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 0);
mShadowPackageManager.setSystemFeature(CONTROLS_FEATURE, false);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_device_controls));
}
@Test
public void getSummary_controlsDisabled() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 0);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 1);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_cards_passes));
}
@Test
public void getSummary_allEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(), CONTROLS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_ENABLED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), CARDS_AVAILABLE, 1);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.power_menu_cards_passes_device_controls));
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2020 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.gestures;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
import java.util.Arrays;
import java.util.Collection;
@RunWith(ParameterizedRobolectricTestRunner.class)
public class PowerMenuPrivacyPreferenceControllerAvailabilityTest {
private static final String CONTROLS_ENABLED = Settings.Secure.CONTROLS_ENABLED;
private static final String CONTROLS_FEATURE = PackageManager.FEATURE_CONTROLS;
private static final String CARDS_ENABLED = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
private static final String CARDS_AVAILABLE = Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
@ParameterizedRobolectricTestRunner.Parameters(
name = "ctrls available={0}, ctrls enabled={1}, cards available={2}, cards enabled={3}")
public static Collection data() {
return Arrays.asList(new Object[][]{
// controls available, controls enabled, cards available, cards enabled, available
{false, false, false, false, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{false, false, false, true, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{false, false, true, false, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{false, false, true, true, BasePreferenceController.AVAILABLE},
{false, true, false, false, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{false, true, false, true, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{false, true, true, false, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{false, true, true, true, BasePreferenceController.AVAILABLE},
{true, false, false, false, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{true, false, false, true, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{true, false, true, false, BasePreferenceController.DISABLED_DEPENDENT_SETTING},
{true, false, true, true, BasePreferenceController.AVAILABLE},
{true, true, false, false, BasePreferenceController.AVAILABLE},
{true, true, false, true, BasePreferenceController.AVAILABLE},
{true, true, true, false, BasePreferenceController.AVAILABLE},
{true, true, true, true, BasePreferenceController.AVAILABLE}
});
}
private Context mContext;
private PowerMenuPrivacyPreferenceController mController;
private ShadowPackageManager mShadowPackageManager;
@Mock
private LockPatternUtils mLockPatternUtils;
private boolean mControlsAvailable;
private boolean mControlsEnabled;
private boolean mCardsAvailable;
private boolean mCardsEnabled;
private int mAvailable;
public PowerMenuPrivacyPreferenceControllerAvailabilityTest(
boolean controlsAvailable,
boolean controlsEnabled,
boolean cardsAvailable,
boolean cardsEnabled,
int available) {
mControlsAvailable = controlsAvailable;
mControlsEnabled = controlsEnabled;
mCardsAvailable = cardsAvailable;
mCardsEnabled = cardsEnabled;
mAvailable = available;
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
// For these tests we assume the device has a secure lock.
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
.thenReturn(mLockPatternUtils);
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
mController = new PowerMenuPrivacyPreferenceController(mContext, "TEST_KEY");
}
@Test
public void getAvailabilityStatus_possiblyAvailableAndEnabled() {
mShadowPackageManager.setSystemFeature(CONTROLS_FEATURE, mControlsAvailable);
ContentResolver cr = mContext.getContentResolver();
Settings.Secure.putInt(cr, CONTROLS_ENABLED, mControlsEnabled ? 1 : 0);
Settings.Secure.putInt(cr, CARDS_AVAILABLE, mCardsAvailable ? 1 : 0);
Settings.Secure.putInt(cr, CARDS_ENABLED, mCardsEnabled ? 1 : 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mAvailable);
}
}

View File

@@ -26,6 +26,7 @@ import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import androidx.preference.Preference;
@@ -42,6 +43,8 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
public class PowerMenuPrivacyPreferenceControllerTest {
@@ -55,6 +58,7 @@ public class PowerMenuPrivacyPreferenceControllerTest {
private Context mContext;
private ContentResolver mContentResolver;
private ShadowPackageManager mShadowPackageManager;
private PowerMenuPrivacyPreferenceController mController;
@Mock
@@ -66,6 +70,8 @@ public class PowerMenuPrivacyPreferenceControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mContentResolver = mContext.getContentResolver();
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
@@ -119,82 +125,50 @@ public class PowerMenuPrivacyPreferenceControllerTest {
}
@Test
public void getSummary_cardsAvailable_isPower_menu_privacy_showString() {
public void getSummary_cardsControlsAvailable_isPower_menu_privacy_showString() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, true);
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.power_menu_privacy_show));
}
@Test
public void getSummary_cardsUnavailable_isPower_menu_privacy_show_controlsString() {
public void
getSummary_cardsUnavailableControlsAvailable_isPower_menu_privacy_show_controlsString() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 0);
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, true);
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.power_menu_privacy_show_controls));
}
@Test
public void
getSummary_cardsAvailableControlsUnavailable_isPower_menu_privacy_show_cardsString() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, false);
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.power_menu_privacy_show_cards));
}
@Test
public void updateState_onPreferenceRefreshed_preferenceEnabledAndSummaryChanged() {
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, true);
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
mController.updateState(mPreference);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference, atLeastOnce()).setSummary(mController.getSummary());
}
@Test
public void getAvailabilityStatus_allOff_returnsDisabled() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 0);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
}
@Test
public void getAvailabilityStatus_cardsUnavailableControlsOff_returnsDisabled() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 0);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
}
@Test
public void testAvailabilityStatus_cardsOnControlsOff_returnsAvailable() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 1);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_cardsOffControlsOn_returnsAvailable() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 0);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_allOn_returnsAvailable() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 1);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_allOnNotSecure_returnsDisabled() {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, true);
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 1);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 1);
@@ -205,9 +179,8 @@ public class PowerMenuPrivacyPreferenceControllerTest {
@Test
public void getAvailabilityStatus_controlsDeletedSecure_retursAvailable() {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
Settings.Secure.putString(mContentResolver, CONTROLS_ENABLED_KEY, null);
mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_CONTROLS, true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);

View File

@@ -32,9 +32,11 @@ import androidx.slice.widget.SliceLiveData;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.EarlyWarningTip;
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
import com.android.settings.slices.SliceBackgroundWorker;
@@ -95,8 +97,14 @@ public class BatteryFixSliceTest {
@Test
public void getSlice_unimportantSlice_shouldSkip() {
final List<BatteryTip> tips = new ArrayList<>();
final List<AppInfo> appList = new ArrayList<>();
appList.add(new AppInfo.Builder()
.setPackageName("com.android.settings")
.setScreenOnTimeMs(10000L)
.build());
tips.add(new LowBatteryTip(BatteryTip.StateType.INVISIBLE, false, ""));
tips.add(new EarlyWarningTip(BatteryTip.StateType.HANDLED, false));
tips.add(new HighUsageTip(1000L, appList));
ShadowBatteryTipLoader.setBatteryTips(tips);
BatteryFixSlice.refreshBatteryTips(mContext);

View File

@@ -60,6 +60,7 @@ public class EnabledNetworkModePreferenceControllerTest {
private static final int SUB_ID = 2;
public static final String KEY = "enabled_network";
private static final long ALLOWED_ALL_NETWORK_TYPE = -1;
private static final long DISABLED_5G_NETWORK_TYPE = ~TelephonyManager.NETWORK_TYPE_BITMASK_NR;
@Mock
@@ -97,6 +98,7 @@ public class EnabledNetworkModePreferenceControllerTest {
doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
mPreference = new ListPreference(mContext);
mController = new EnabledNetworkModePreferenceController(mContext, KEY);
mockAllowedNetworkTypes(ALLOWED_ALL_NETWORK_TYPE);
mockAccessFamily(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
mController.init(mLifecycle, SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
@@ -182,6 +184,76 @@ public class EnabledNetworkModePreferenceControllerTest {
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA));
}
@Test
public void updateState_disAllowed5g_5gOptionHidden() {
mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA);
mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA);
mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE);
mController.init(mLifecycle, SUB_ID);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA);
mController.updateState(mPreference);
assertThat(mPreference.getEntryValues())
.asList()
.doesNotContain(
String.valueOf(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA));
}
@Test
public void updateState_disAllowed5g_selectOn4gOption() {
mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA);
mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA);
mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE);
mController.init(mLifecycle, SUB_ID);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA);
mController.updateState(mPreference);
assertThat(mPreference.getValue()).isEqualTo(
String.valueOf(
TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA));
}
@Test
public void updateState_GlobalDisAllowed5g_GlobalWithoutNR() {
mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA);
mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE);
mController.init(mLifecycle, SUB_ID);
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA);
mController.updateState(mPreference);
assertThat(mPreference.getEntryValues())
.asList()
.doesNotContain(
String.valueOf(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA));
}
@Test
public void updateState_GlobalDisAllowed5g_SelectOnGlobal() {
mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA);
mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE);
mController.init(mLifecycle, SUB_ID);
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA);
mController.updateState(mPreference);
assertThat(mPreference.getValue()).isEqualTo(
String.valueOf(
TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA));
}
@Test
public void updateState_updateByNetworkMode() {
mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
@@ -279,6 +351,10 @@ public class EnabledNetworkModePreferenceControllerTest {
}
}
private void mockAllowedNetworkTypes(long allowedNetworkType) {
doReturn(allowedNetworkType).when(mTelephonyManager).getAllowedNetworkTypes();
}
private void mockAccessFamily(int networkMode) {
doReturn(MobileNetworkUtils.getRafFromNetworkType(networkMode))
.when(mTelephonyManager)

View File

@@ -28,7 +28,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.widget.EditText;
import android.widget.ImageView;
@@ -62,6 +64,8 @@ public class EditUserInfoControllerTest {
@Mock
private Drawable mCurrentIcon;
private boolean mCanChangePhoto;
private FragmentActivity mActivity;
private TestEditUserInfoController mController;
@@ -78,6 +82,11 @@ public class EditUserInfoControllerTest {
mPhotoController = mock(EditUserPhotoController.class, Answers.RETURNS_DEEP_STUBS);
return mPhotoController;
}
@Override
boolean canChangePhoto(Context context, UserInfo user) {
return mCanChangePhoto;
}
}
@Before
@@ -86,6 +95,7 @@ public class EditUserInfoControllerTest {
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
when(mFragment.getActivity()).thenReturn(mActivity);
mController = new TestEditUserInfoController();
mCanChangePhoto = true;
}
@Test
@@ -256,4 +266,17 @@ public class EditUserInfoControllerTest {
verify(dialogCompleteCallback, times(1)).onPositive();
verify(dialogCompleteCallback, times(0)).onNegativeOrCancel();
}
@Test
public void createDialog_canNotChangePhoto_nullPhotoController() {
mCanChangePhoto = false;
mController.createDialog(
mFragment, mCurrentIcon, "test",
"title", null,
android.os.Process.myUserHandle(),
null);
assertThat(mController.mPhotoController).isNull();
}
}

View File

@@ -32,9 +32,11 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.robolectric.Shadows.shadowOf;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
@@ -47,6 +49,8 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -61,6 +65,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowIntent;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
@@ -76,6 +81,7 @@ public class UserDetailsSettingsTest {
private static final String KEY_SWITCH_USER = "switch_user";
private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
private static final String KEY_REMOVE_USER = "remove_user";
private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
private static final int DIALOG_CONFIRM_REMOVE = 1;
@@ -90,6 +96,8 @@ public class UserDetailsSettingsTest {
private SwitchPreference mPhonePref;
@Mock
private Preference mRemoveUserPref;
@Mock
private Preference mAppAndContentAccessPref;
private FragmentActivity mActivity;
private Context mContext;
@@ -114,14 +122,15 @@ public class UserDetailsSettingsTest {
ReflectionHelpers.setField(mFragment, "mUserManager", userManager);
doReturn(mActivity).when(mFragment).getActivity();
doReturn(mContext).when(mFragment).getContext();
doReturn(mActivity).when(mFragment).getContext();
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
doReturn("").when(mActivity).getString(anyInt(), anyString());
doReturn(mSwitchUserPref).when(mFragment).findPreference(KEY_SWITCH_USER);
doReturn(mPhonePref).when(mFragment).findPreference(KEY_ENABLE_TELEPHONY);
doReturn(mRemoveUserPref).when(mFragment).findPreference(KEY_REMOVE_USER);
doReturn(mAppAndContentAccessPref)
.when(mFragment).findPreference(KEY_APP_AND_CONTENT_ACCESS);
}
@After
@@ -169,6 +178,24 @@ public class UserDetailsSettingsTest {
verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
}
@Test
public void initialize_userSelected_shouldNotShowAppAndContentPref() {
setupSelectedUser();
mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
@Test
public void initialize_guestSelected_shouldNotShowAppAndContentPref() {
setupSelectedGuest();
mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
@Test
public void onResume_canSwitch_shouldEnableSwitchPref() {
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
@@ -248,6 +275,16 @@ public class UserDetailsSettingsTest {
verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
}
@Test
public void initialize_nonAdmin_shouldNotShowAppAndContentPref() {
setupSelectedUser();
mUserManager.setIsAdminUser(false);
mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
@Test
public void initialize_adminSelectsSecondaryUser_shouldShowRemovePreference() {
setupSelectedUser();
@@ -260,6 +297,57 @@ public class UserDetailsSettingsTest {
verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
}
@Test
public void initialize_adminSelectsNewRestrictedUser_shouldOpenAppContentScreen() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
mArguments.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, true);
mFragment.initialize(mActivity, mArguments);
Intent startedIntent = shadowOf(mActivity).getNextStartedActivity();
ShadowIntent shadowIntent = shadowOf(startedIntent);
assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class);
assertThat(startedIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(AppRestrictionsFragment.class.getName());
Bundle arguments = startedIntent.getBundleExtra(
SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
assertThat(arguments).isNotNull();
assertThat(arguments.getInt(AppRestrictionsFragment.EXTRA_USER_ID, 0))
.isEqualTo(mUserInfo.id);
assertThat(arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false))
.isEqualTo(true);
}
@Test
public void initialize_adminSelectsRestrictedUser_shouldSetupPreferences() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
doReturn(true).when(mTelephonyManager).isVoiceCapable();
mFragment.initialize(mActivity, mArguments);
verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
verify(mFragment, never()).removePreference(KEY_APP_AND_CONTENT_ACCESS);
verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
verify(mSwitchUserPref).setTitle("Switch to " + mUserInfo.name);
verify(mAppAndContentAccessPref).setOnPreferenceClickListener(mFragment);
verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
verify(mRemoveUserPref).setOnPreferenceClickListener(mFragment);
}
@Test
public void initialize_adminSelectsExistingRestrictedUser_shouldNotStartAppAndContentAccess() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
mArguments.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
mFragment.initialize(mActivity, mArguments);
verify(mActivity, never()).startActivity(any(Intent.class));
}
@Test
public void initialize_adminSelectsGuest_shouldShowRemovePreference() {
setupSelectedGuest();
@@ -344,6 +432,7 @@ public class UserDetailsSettingsTest {
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.mUserInfo = mUserInfo;
mFragment.onPreferenceClick(mSwitchUserPref);
@@ -357,6 +446,7 @@ public class UserDetailsSettingsTest {
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED);
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.mUserInfo = mUserInfo;
mFragment.onPreferenceClick(mSwitchUserPref);
@@ -371,6 +461,7 @@ public class UserDetailsSettingsTest {
mUserManager.setIsAdminUser(true);
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
doNothing().when(mFragment).showDialog(anyInt());
mFragment.onPreferenceClick(mRemoveUserPref);
@@ -386,6 +477,7 @@ public class UserDetailsSettingsTest {
mUserManager.setIsAdminUser(false);
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
doNothing().when(mFragment).showDialog(anyInt());
mFragment.onPreferenceClick(mRemoveUserPref);
@@ -394,12 +486,37 @@ public class UserDetailsSettingsTest {
verify(mFragment, never()).showDialog(DIALOG_CONFIRM_REMOVE);
}
@Test
public void onPreferenceClick_selectRestrictedUser_appAndContentAccessClicked_startActivity() {
setupSelectedRestrictedUser();
mFragment.mUserInfo = mUserInfo;
mUserManager.setIsAdminUser(true);
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.onPreferenceClick(mAppAndContentAccessPref);
Intent startedIntent = shadowOf(mActivity).getNextStartedActivity();
ShadowIntent shadowIntent = shadowOf(startedIntent);
assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class);
assertThat(startedIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(AppRestrictionsFragment.class.getName());
Bundle arguments = startedIntent.getBundleExtra(
SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
assertThat(arguments.getInt(AppRestrictionsFragment.EXTRA_USER_ID, 0))
.isEqualTo(mUserInfo.id);
assertThat(arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, true))
.isEqualTo(false);
}
@Test
public void onPreferenceClick_unknownPreferenceClicked_doNothing() {
setupSelectedUser();
mFragment.mUserInfo = mUserInfo;
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.onPreferenceClick(mock(UserPreference.class));
@@ -464,4 +581,13 @@ public class UserDetailsSettingsTest {
mUserManager.addProfile(mUserInfo);
}
private void setupSelectedRestrictedUser() {
mArguments.putInt("user_id", 21);
mUserInfo = new UserInfo(21, "Bob", null,
UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_RESTRICTED,
UserManager.USER_TYPE_FULL_RESTRICTED);
mUserManager.addProfile(mUserInfo);
}
}