Update Work profile settings
Change work apps toggle to a primary toggle make Xprofile contact search toggle disable/enable when work profile is turned off Add footer and change strings Add tests Test: atest ContactSearchPreferenceControllerTest, atest WorkModePreferenceControllerTest Bug: 253009702 275538029 Change-Id: I3b2044a5fe3f2aff0748d66e701a3f0d7667ab7a
This commit is contained in:
@@ -5873,12 +5873,8 @@
|
||||
<string name="add_account_label">Add account</string>
|
||||
<!-- Label for the state of the work profile [CHAR LIMIT=80] -->
|
||||
<string name="managed_profile_not_available_label">Work profile isn\u2019t available yet</string>
|
||||
<!-- This string is the title of a setting. If a user taps the setting, they can turn their work profile on or off. The work profile is a section of their phone that's managed by their employer. "Work" is an adjective. -->
|
||||
<string name="work_mode_label">Work profile</string>
|
||||
<!-- This string is located under a setting and describes what the setting does. It's letting a user know whether their work profile is on or off, and they can use the setting to turn it on or off. The work profile is a section of their phone that's managed by their employer. "Work" is an adjective.-->
|
||||
<string name="work_mode_on_summary">Managed by your organization</string>
|
||||
<!-- This string is located under a setting and describes what the setting does. It's letting a user know whether their work profile is on or off, and they can use the setting to turn it on or off. The work profile is a section of their phone that's managed by their employer. "Work" is an adjective.-->
|
||||
<string name="work_mode_off_summary">Apps and notifications are off</string>
|
||||
<!-- This string is the title of a setting. If a user taps the setting, they can turn their work apps on or off. The work apps are a group of apps that are managed by the the user's employer. While this setting is off, the user cannot interact with those apps or get notifications from them. "Work" is an adjective. -->
|
||||
<string name="work_mode_label">Work apps</string>
|
||||
<!-- Button label to remove the work profile [CHAR LIMIT=35] -->
|
||||
<string name="remove_managed_profile_label">Remove work profile</string>
|
||||
<!-- Data synchronization settings screen, title of setting that controls whether background data should be used [CHAR LIMIT=30] -->
|
||||
@@ -9779,6 +9775,8 @@
|
||||
<string name="cross_profile_calendar_title">Cross-profile calendar</string>
|
||||
<!-- [CHAR LIMIT=NONE] Setting description. If the user turns on this setting, they can see their work events on their personal calendar. -->
|
||||
<string name="cross_profile_calendar_summary">Show work events on your personal calendar</string>
|
||||
<!-- [CHAR_LIMIT_NONE] Footer description. Explains to the user what will happen when work apps are turned off. -->
|
||||
<string name="managed_profile_settings_footer">When work apps are off, they’re paused and can’t be accessed or send you notifications</string>
|
||||
|
||||
<!-- Used as title on the automatic storage manager settings. [CHAR LIMIT=60] -->
|
||||
<string name="automatic_storage_manager_settings">Manage storage</string>
|
||||
|
@@ -19,10 +19,9 @@
|
||||
android:key="managed_profile_settings_screen"
|
||||
android:title="@string/managed_profile_settings_title">
|
||||
|
||||
<SwitchPreference
|
||||
<com.android.settingslib.widget.MainSwitchPreference
|
||||
android:key="work_mode"
|
||||
android:title="@string/work_mode_label"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:controller="com.android.settings.accounts.WorkModePreferenceController"/>
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
@@ -38,4 +37,9 @@
|
||||
android:title="@string/cross_profile_calendar_title"
|
||||
settings:controller="com.android.settings.accounts.CrossProfileCalendarPreferenceController"/>
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:title="@string/managed_profile_settings_footer"
|
||||
android:key="managed_profile_footer"
|
||||
settings:searchable="false"/>
|
||||
|
||||
</PreferenceScreen>
|
@@ -20,37 +20,38 @@ import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settings.slices.SliceData;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
public class ContactSearchPreferenceController extends BasePreferenceController implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
private UserHandle mManagedUser;
|
||||
public class ContactSearchPreferenceController extends TogglePreferenceController implements
|
||||
Preference.OnPreferenceChangeListener, DefaultLifecycleObserver,
|
||||
ManagedProfileQuietModeEnabler.QuietModeChangeListener {
|
||||
|
||||
private final ManagedProfileQuietModeEnabler mQuietModeEnabler;
|
||||
private final UserHandle mManagedUser;
|
||||
private Preference mPreference;
|
||||
|
||||
public ContactSearchPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
// Set default managed profile for the current user, otherwise isAvailable will be false and
|
||||
// the setting won't be searchable.
|
||||
UserManager userManager = context.getSystemService(UserManager.class);
|
||||
mManagedUser = Utils.getManagedProfile(userManager);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setManagedUser(UserHandle managedUser) {
|
||||
mManagedUser = managedUser;
|
||||
mManagedUser = Utils.getManagedProfile(context.getSystemService(UserManager.class));
|
||||
mQuietModeEnabler = new ManagedProfileQuietModeEnabler(context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return (mManagedUser != null) ? AVAILABLE : DISABLED_FOR_USER;
|
||||
return mQuietModeEnabler.isAvailable() ? AVAILABLE : DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,6 +60,7 @@ public class ContactSearchPreferenceController extends BasePreferenceController
|
||||
if (preference instanceof RestrictedSwitchPreference) {
|
||||
final RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setChecked(isChecked());
|
||||
pref.setEnabled(!mQuietModeEnabler.isQuietModeEnabled());
|
||||
if (mManagedUser != null) {
|
||||
final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
|
||||
RestrictedLockUtilsInternal.checkIfRemoteContactSearchDisallowed(
|
||||
@@ -68,26 +70,48 @@ public class ContactSearchPreferenceController extends BasePreferenceController
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isChecked() {
|
||||
if (mManagedUser == null) {
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
updateState(mPreference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NotNull LifecycleOwner lifecycleOwner) {
|
||||
lifecycleOwner.getLifecycle().addObserver(mQuietModeEnabler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(@NotNull LifecycleOwner lifecycleOwner) {
|
||||
lifecycleOwner.getLifecycle().removeObserver(mQuietModeEnabler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
if (mManagedUser == null || mQuietModeEnabler.isQuietModeEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return 0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 0, mManagedUser.getIdentifier());
|
||||
}
|
||||
|
||||
private boolean setChecked(boolean isChecked) {
|
||||
if (mManagedUser != null) {
|
||||
final int value = isChecked ? 1 : 0;
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, value, mManagedUser.getIdentifier());
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
if (mManagedUser == null || mQuietModeEnabler.isQuietModeEnabled()) {
|
||||
return false;
|
||||
}
|
||||
final int value = isChecked ? 1 : 0;
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, value, mManagedUser.getIdentifier());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
return setChecked((boolean) newValue);
|
||||
public void onQuietModeChanged() {
|
||||
if (mPreference != null) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,4 +119,9 @@ public class ContactSearchPreferenceController extends BasePreferenceController
|
||||
public int getSliceType() {
|
||||
return SliceData.SliceType.SWITCH;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSliceHighlightMenuRes() {
|
||||
return R.string.menu_key_accounts;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.accounts;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A class that controls the managed profile's quiet mode, listens to quiet mode changes and
|
||||
* modifies managed profile settings. The user facing term for quiet mode is "work apps".
|
||||
*/
|
||||
final class ManagedProfileQuietModeEnabler implements DefaultLifecycleObserver {
|
||||
|
||||
private static final String TAG = "QuietModeEnabler";
|
||||
private final Context mContext;
|
||||
private final QuietModeChangeListener mListener;
|
||||
@Nullable private final UserHandle mManagedProfile;
|
||||
private final UserManager mUserManager;
|
||||
|
||||
public interface QuietModeChangeListener {
|
||||
/** Called when quiet mode has changed. */
|
||||
void onQuietModeChanged();
|
||||
}
|
||||
|
||||
ManagedProfileQuietModeEnabler(Context context, QuietModeChangeListener listener) {
|
||||
mContext = context;
|
||||
mListener = listener;
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
mManagedProfile = Utils.getManagedProfile(mUserManager);
|
||||
}
|
||||
|
||||
public void setQuietModeEnabled(boolean enabled) {
|
||||
if (mManagedProfile != null) {
|
||||
mUserManager.requestQuietModeEnabled(enabled, mManagedProfile);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isQuietModeEnabled() {
|
||||
return mManagedProfile != null && mUserManager.isQuietModeEnabled(mManagedProfile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NonNull LifecycleOwner owner) {
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
|
||||
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
|
||||
mContext.registerReceiver(mReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner) {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return (mManagedProfile != null);
|
||||
}
|
||||
|
||||
private void refreshQuietMode() {
|
||||
if (mListener != null) {
|
||||
mListener.onQuietModeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receiver that listens to {@link Intent#ACTION_MANAGED_PROFILE_AVAILABLE} and
|
||||
* {@link Intent#ACTION_MANAGED_PROFILE_UNAVAILABLE}, and updates the work mode
|
||||
*/
|
||||
@VisibleForTesting
|
||||
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
String action = intent.getAction();
|
||||
Log.v(TAG, "Received broadcast: " + action);
|
||||
|
||||
if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
|
||||
|| Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
|
||||
int intentUserIdentifier = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
|
||||
UserHandle.USER_NULL);
|
||||
if (intentUserIdentifier == mManagedProfile.getIdentifier()) {
|
||||
refreshQuietMode();
|
||||
} else {
|
||||
Log.w(TAG, "Managed profile broadcast ID: " + intentUserIdentifier
|
||||
+ " does not match managed user: " + mManagedProfile);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@@ -1,165 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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
|
||||
* 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.
|
||||
* 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.accounts;
|
||||
|
||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SETTING_OFF_SUMMARY;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SETTING_ON_SUMMARY;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.slices.SliceData;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
import com.android.settings.widget.SettingsMainSwitchPreferenceController;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
public class WorkModePreferenceController extends BasePreferenceController implements
|
||||
Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart, OnStop {
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
private static final String TAG = "WorkModeController";
|
||||
|
||||
private UserManager mUserManager;
|
||||
private UserHandle mManagedUser;
|
||||
private DevicePolicyManager mDevicePolicyManager;
|
||||
public class WorkModePreferenceController extends SettingsMainSwitchPreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, DefaultLifecycleObserver,
|
||||
ManagedProfileQuietModeEnabler.QuietModeChangeListener {
|
||||
|
||||
private Preference mPreference;
|
||||
private IntentFilter mIntentFilter;
|
||||
private final ManagedProfileQuietModeEnabler mQuietModeEnabler;
|
||||
|
||||
public WorkModePreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
|
||||
mIntentFilter = new IntentFilter();
|
||||
mIntentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
|
||||
mIntentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
|
||||
// Set default managed profile for the current user, otherwise isAvailable will be false and
|
||||
// the setting won't be searchable.
|
||||
mManagedUser = Utils.getManagedProfile(mUserManager);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setManagedUser(UserHandle managedUser) {
|
||||
mManagedUser = managedUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mContext.registerReceiver(mReceiver, mIntentFilter,
|
||||
Context.RECEIVER_EXPORTED_UNAUDITED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
mQuietModeEnabler = new ManagedProfileQuietModeEnabler(context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return (mManagedUser != null) ? AVAILABLE : DISABLED_FOR_USER;
|
||||
return (mQuietModeEnabler.isAvailable()) ? AVAILABLE : DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
public void onStart(@NotNull LifecycleOwner lifecycleOwner) {
|
||||
lifecycleOwner.getLifecycle().addObserver(mQuietModeEnabler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
if (isChecked()) {
|
||||
return mDevicePolicyManager.getResources().getString(
|
||||
WORK_PROFILE_SETTING_ON_SUMMARY,
|
||||
() -> mContext.getString(R.string.work_mode_on_summary));
|
||||
}
|
||||
|
||||
return mDevicePolicyManager.getResources().getString(
|
||||
WORK_PROFILE_SETTING_OFF_SUMMARY,
|
||||
() -> mContext.getString(R.string.work_mode_off_summary));
|
||||
public void onStop(@NotNull LifecycleOwner lifecycleOwner) {
|
||||
lifecycleOwner.getLifecycle().removeObserver(mQuietModeEnabler);
|
||||
}
|
||||
|
||||
private boolean isChecked() {
|
||||
boolean isWorkModeOn = false;
|
||||
if (mUserManager != null && mManagedUser != null) {
|
||||
isWorkModeOn = !mUserManager.isQuietModeEnabled(mManagedUser);
|
||||
}
|
||||
return isWorkModeOn;
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return !mQuietModeEnabler.isQuietModeEnabled();
|
||||
}
|
||||
|
||||
private boolean setChecked(boolean isChecked) {
|
||||
if (mUserManager != null && mManagedUser != null) {
|
||||
final boolean quietModeEnabled = !isChecked;
|
||||
mUserManager.requestQuietModeEnabled(quietModeEnabled, mManagedUser);
|
||||
}
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
mQuietModeEnabler.setQuietModeEnabled(!isChecked);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
if (preference instanceof TwoStatePreference) {
|
||||
((TwoStatePreference) preference).setChecked(isChecked());
|
||||
}
|
||||
public void onQuietModeChanged() {
|
||||
updateState(mSwitchPreference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
return setChecked((boolean) newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receiver that listens to {@link Intent#ACTION_MANAGED_PROFILE_AVAILABLE} and
|
||||
* {@link Intent#ACTION_MANAGED_PROFILE_UNAVAILABLE}, and updates the work mode
|
||||
*/
|
||||
@VisibleForTesting
|
||||
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
final String action = intent.getAction();
|
||||
Log.v(TAG, "Received broadcast: " + action);
|
||||
|
||||
if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
|
||||
|| Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
|
||||
if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
|
||||
UserHandle.USER_NULL) == mManagedUser.getIdentifier()) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
@SliceData.SliceType
|
||||
public int getSliceType() {
|
||||
return SliceData.SliceType.SWITCH;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSliceHighlightMenuRes() {
|
||||
return R.string.menu_key_accounts;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setPreference(MainSwitchPreference preference) {
|
||||
mSwitchPreference = preference;
|
||||
}
|
||||
}
|
||||
|
@@ -20,13 +20,19 @@ import static android.provider.Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SE
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -35,39 +41,51 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ContactSearchPreferenceControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "contacts_search";
|
||||
|
||||
@Mock
|
||||
private UserHandle mManagedUser;
|
||||
private static final int MANAGED_USER_ID = 10;
|
||||
|
||||
private Context mContext;
|
||||
private ContactSearchPreferenceController mController;
|
||||
private RestrictedSwitchPreference mPreference;
|
||||
|
||||
@Mock
|
||||
private UserHandle mManagedUser;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private UserInfo mUserInfo;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new ContactSearchPreferenceController(mContext, PREF_KEY);
|
||||
mController.setManagedUser(mManagedUser);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
mPreference = spy(new RestrictedSwitchPreference(mContext));
|
||||
when(mUserInfo.isManagedProfile()).thenReturn(true);
|
||||
when(mUserManager.getUserInfo(anyInt())).thenReturn(mUserInfo);
|
||||
when(mUserManager.getProcessUserId()).thenReturn(0);
|
||||
when(mUserManager.getUserProfiles()).thenReturn(Collections.singletonList(mManagedUser));
|
||||
when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID);
|
||||
mController = new ContactSearchPreferenceController(mContext, PREF_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noManagedUser_DISABLED() {
|
||||
mController.setManagedUser(null);
|
||||
when(mUserManager.getProcessUserId()).thenReturn(MANAGED_USER_ID);
|
||||
mController = new ContactSearchPreferenceController(mContext, PREF_KEY);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isNotEqualTo(ContactSearchPreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hasManagedUser_AVAILABLE() {
|
||||
mController.setManagedUser(mManagedUser);
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(ContactSearchPreferenceController.AVAILABLE);
|
||||
}
|
||||
@@ -75,32 +93,96 @@ public class ContactSearchPreferenceControllerTest {
|
||||
@Test
|
||||
public void updateState_shouldRefreshContent() {
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 0, mManagedUser.getIdentifier());
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 0, MANAGED_USER_ID);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 1, mManagedUser.getIdentifier());
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 1, MANAGED_USER_ID);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_preferenceShouldBeDisabled() {
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setDisabledByAdmin(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_shouldUpdateProviderValue() {
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
|
||||
assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 1, mManagedUser.getIdentifier()))
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 1, MANAGED_USER_ID))
|
||||
.isEqualTo(0);
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 0, mManagedUser.getIdentifier()))
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 0, MANAGED_USER_ID))
|
||||
.isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onQuietModeDisabled_preferenceEnabled() {
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onQuietModeEnabled_preferenceDisabledAndUnchecked() {
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterQuietModeTurnedOnAndOffWhenPreferenceChecked_toggleCheckedAndEnabled() {
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 1, MANAGED_USER_ID);
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterQuietModeTurnedOnAndOffWhenPreferenceUnchecked_toggleUncheckedAndEnabled() {
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, 0, MANAGED_USER_ID);
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.accounts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ManagedProfileQuietModeEnablerTest {
|
||||
private static final int MANAGED_USER_ID = 10;
|
||||
private Context mContext;
|
||||
private ManagedProfileQuietModeEnabler mQuietModeEnabler;
|
||||
private LifecycleOwner mLifecycleOwner = new LifecycleOwner() {
|
||||
public LifecycleRegistry registry = new LifecycleRegistry(this);
|
||||
|
||||
@Override
|
||||
public Lifecycle getLifecycle() {
|
||||
return registry;
|
||||
}
|
||||
};
|
||||
|
||||
@Mock
|
||||
private ManagedProfileQuietModeEnabler.QuietModeChangeListener mOnQuietModeChangeListener;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private UserHandle mManagedUser;
|
||||
@Mock
|
||||
private UserInfo mUserInfo;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mUserInfo.isManagedProfile()).thenReturn(true);
|
||||
when(mUserManager.getUserInfo(anyInt())).thenReturn(mUserInfo);
|
||||
when(mUserManager.getProcessUserId()).thenReturn(0);
|
||||
when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID);
|
||||
when(mUserManager.getUserProfiles()).thenReturn(Collections.singletonList(mManagedUser));
|
||||
mQuietModeEnabler = new ManagedProfileQuietModeEnabler(mContext,
|
||||
mOnQuietModeChangeListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSetQuietMode_shouldRequestQuietModeEnabled() {
|
||||
mQuietModeEnabler.setQuietModeEnabled(false);
|
||||
verify(mUserManager).requestQuietModeEnabled(false, mManagedUser);
|
||||
mQuietModeEnabler.setQuietModeEnabled(true);
|
||||
verify(mUserManager).requestQuietModeEnabled(true, mManagedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onIsQuietModeEnabled_shouldCallIsQuietModeEnabled() {
|
||||
assertThat(mQuietModeEnabler.isQuietModeEnabled()).isEqualTo(
|
||||
verify(mUserManager).isQuietModeEnabled(any()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onQuietModeChanged_listenerNotified() {
|
||||
mQuietModeEnabler.onStart(mLifecycleOwner);
|
||||
mContext.sendBroadcast(new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABLE).putExtra(
|
||||
Intent.EXTRA_USER_HANDLE, MANAGED_USER_ID));
|
||||
mContext.sendBroadcast(new Intent(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE).putExtra(
|
||||
Intent.EXTRA_USER_HANDLE, MANAGED_USER_ID));
|
||||
verify(mOnQuietModeChangeListener, times(2)).onQuietModeChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_shouldRegisterReceiver() {
|
||||
mQuietModeEnabler.onStart(mLifecycleOwner);
|
||||
verify(mContext).registerReceiver(eq(mQuietModeEnabler.mReceiver), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_shouldUnregisterReceiver() {
|
||||
// register it first
|
||||
mContext.registerReceiver(mQuietModeEnabler.mReceiver, null,
|
||||
Context.RECEIVER_EXPORTED/*UNAUDITED*/);
|
||||
|
||||
mQuietModeEnabler.onStop(mLifecycleOwner);
|
||||
verify(mContext).unregisterReceiver(mQuietModeEnabler.mReceiver);
|
||||
}
|
||||
}
|
@@ -19,18 +19,18 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -38,43 +38,51 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class WorkModePreferenceControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "work_mode";
|
||||
private static final int MANAGED_USER_ID = 10;
|
||||
|
||||
private Context mContext;
|
||||
private WorkModePreferenceController mController;
|
||||
private MainSwitchPreference mPreference;
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private UserHandle mManagedUser;
|
||||
|
||||
private Context mContext;
|
||||
private WorkModePreferenceController mController;
|
||||
private SwitchPreference mPreference;
|
||||
@Mock
|
||||
private UserInfo mUserInfo;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
mPreference = new MainSwitchPreference(mContext);
|
||||
when(mUserInfo.isManagedProfile()).thenReturn(true);
|
||||
when(mUserManager.getUserInfo(anyInt())).thenReturn(mUserInfo);
|
||||
when(mUserManager.getProcessUserId()).thenReturn(0);
|
||||
when(mUserManager.getUserProfiles()).thenReturn(Collections.singletonList(mManagedUser));
|
||||
when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID);
|
||||
mController = new WorkModePreferenceController(mContext, PREF_KEY);
|
||||
mController.setManagedUser(mManagedUser);
|
||||
mPreference = new SwitchPreference(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noManagedUser_DISABLED() {
|
||||
mController.setManagedUser(null);
|
||||
when(mUserManager.getProcessUserId()).thenReturn(MANAGED_USER_ID);
|
||||
mController = new WorkModePreferenceController(mContext, PREF_KEY);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isNotEqualTo(WorkModePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hasManagedUser_AVAILABLE() {
|
||||
mController.setManagedUser(mManagedUser);
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(WorkModePreferenceController.AVAILABLE);
|
||||
}
|
||||
@@ -83,41 +91,29 @@ public class WorkModePreferenceControllerTest {
|
||||
public void updateState_shouldRefreshContent() {
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class)))
|
||||
.thenReturn(false);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
assertThat(mPreference.getSummary())
|
||||
.isEqualTo(mContext.getText(R.string.work_mode_on_summary));
|
||||
|
||||
when(mUserManager.isQuietModeEnabled(any(UserHandle.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
assertThat(mPreference.getSummary())
|
||||
.isEqualTo(mContext.getText(R.string.work_mode_off_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_shouldRequestQuietModeEnabled() {
|
||||
mController.setPreference(mPreference);
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
verify(mUserManager).requestQuietModeEnabled(false, mManagedUser);
|
||||
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
|
||||
verify(mUserManager).requestQuietModeEnabled(true, mManagedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_shouldRegisterReceiver() {
|
||||
mController.onStart();
|
||||
verify(mContext).registerReceiver(eq(mController.mReceiver), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_shouldUnregisterReceiver() {
|
||||
// register it first
|
||||
mContext.registerReceiver(mController.mReceiver, null,
|
||||
Context.RECEIVER_EXPORTED/*UNAUDITED*/);
|
||||
|
||||
mController.onStop();
|
||||
verify(mContext).unregisterReceiver(mController.mReceiver);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user