diff --git a/res/drawable/ic_download_for_offline.xml b/res/drawable/ic_download_for_offline.xml new file mode 100644 index 00000000000..f9ea3050f55 --- /dev/null +++ b/res/drawable/ic_download_for_offline.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/res/drawable/zen_calls_any.xml b/res/drawable/zen_calls_any.xml new file mode 100644 index 00000000000..546fd93395a --- /dev/null +++ b/res/drawable/zen_calls_any.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + diff --git a/res/drawable/zen_calls_contacts.xml b/res/drawable/zen_calls_contacts.xml new file mode 100644 index 00000000000..a4c064a76e5 --- /dev/null +++ b/res/drawable/zen_calls_contacts.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/zen_calls_none.xml b/res/drawable/zen_calls_none.xml new file mode 100644 index 00000000000..e89da49d7b6 --- /dev/null +++ b/res/drawable/zen_calls_none.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/res/drawable/zen_calls_starred.xml b/res/drawable/zen_calls_starred.xml new file mode 100644 index 00000000000..25e9a6193eb --- /dev/null +++ b/res/drawable/zen_calls_starred.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/zen_messages_any.xml b/res/drawable/zen_messages_any.xml new file mode 100644 index 00000000000..edeaea2726c --- /dev/null +++ b/res/drawable/zen_messages_any.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + diff --git a/res/drawable/zen_messages_contacts.xml b/res/drawable/zen_messages_contacts.xml new file mode 100644 index 00000000000..8da80b94a0b --- /dev/null +++ b/res/drawable/zen_messages_contacts.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/zen_messages_none.xml b/res/drawable/zen_messages_none.xml new file mode 100644 index 00000000000..c72cc4f133c --- /dev/null +++ b/res/drawable/zen_messages_none.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/res/drawable/zen_messages_starred.xml b/res/drawable/zen_messages_starred.xml new file mode 100644 index 00000000000..75feb80d711 --- /dev/null +++ b/res/drawable/zen_messages_starred.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + diff --git a/res/layout/zen_mode_senders_image.xml b/res/layout/zen_mode_senders_image.xml new file mode 100644 index 00000000000..bc7cdae2627 --- /dev/null +++ b/res/layout/zen_mode_senders_image.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 450eb1301a1..834f04c1746 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7004,7 +7004,7 @@ Except when another payment app is open - At a Tap & pay terminal, pay with: + At a contactless terminal, pay with: Paying at the terminal @@ -7015,9 +7015,21 @@ More... - Set as your preference? - Always use %1$s when you Tap & pay? - Always use %1$s instead of %2$s when you Tap & pay? + Set default payment app + + Update default payment app + At a contactless terminal, pay with + %1$s + + At a contactless terminal, pay with %1$s.\n\nThis replaces %2$s as your default + payment app. + + + Set default + + Update @@ -8525,6 +8537,12 @@ When a user connects select work and personal apps, they can access work and personal data together. [CHAR LIMIT=50] --> Connected work & personal apps + + Connected + + + Not connected + No connected apps @@ -8591,27 +8609,18 @@ - Install %1$s in your work profile - - - To connect these apps, install the %1$s app in your work profile + Install work %1$s to connect these apps - Install %1$s in your personal profile + The placeholder would be the app name (e.g. Calendar). [CHAR LIMIT=NONE]--> + Install personal %1$s to connect these apps - To connect these apps, install the %1$s app in your personal profile - - - Get the app + Tap to get the app Do Not Disturb access @@ -10548,9 +10557,6 @@ Cross-profile calendar Show work events on your personal calendar - - Your organization doesn\u2019t allow personal apps to access your work calendar - diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml index 4078e824819..3dcddc8eb19 100644 --- a/res/xml/configure_notification_settings.xml +++ b/res/xml/configure_notification_settings.xml @@ -140,11 +140,6 @@ android:ringtoneType="notification" settings:searchable="false"/> - - - - + - + - + - + + + diff --git a/res/xml/managed_profile_settings.xml b/res/xml/managed_profile_settings.xml index 7b65a3d30b0..20f6d3dc3f3 100644 --- a/res/xml/managed_profile_settings.xml +++ b/res/xml/managed_profile_settings.xml @@ -32,18 +32,10 @@ settings:useAdditionalSummary="true" settings:controller="com.android.settings.accounts.ContactSearchPreferenceController"/> - - \ No newline at end of file diff --git a/res/xml/zen_mode_calls_settings.xml b/res/xml/zen_mode_calls_settings.xml index cbadc7d7ce4..0b44875a3ec 100644 --- a/res/xml/zen_mode_calls_settings.xml +++ b/res/xml/zen_mode_calls_settings.xml @@ -25,6 +25,11 @@ android:key="zen_mode_settings_category_calls" android:title="@string/zen_mode_calls_header" settings:allowDividerBelow="true"> + + + diff --git a/res/xml/zen_mode_messages_settings.xml b/res/xml/zen_mode_messages_settings.xml index c302b02b72e..31cad2a5347 100644 --- a/res/xml/zen_mode_messages_settings.xml +++ b/res/xml/zen_mode_messages_settings.xml @@ -23,6 +23,11 @@ + + + diff --git a/src/com/android/settings/accounts/CrossProfileCalendarDisabledPreferenceController.java b/src/com/android/settings/accounts/CrossProfileCalendarDisabledPreferenceController.java deleted file mode 100644 index c0879823792..00000000000 --- a/src/com/android/settings/accounts/CrossProfileCalendarDisabledPreferenceController.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2019 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.android.settings.accounts.CrossProfileCalendarPreferenceController.isCrossProfileCalendarDisallowedByAdmin; - -import android.content.Context; -import android.os.UserHandle; - -import com.android.settings.core.BasePreferenceController; - -public class CrossProfileCalendarDisabledPreferenceController extends BasePreferenceController { - private UserHandle mManagedUser; - - public void setManagedUser(UserHandle managedUser) { - mManagedUser = managedUser; - } - - public CrossProfileCalendarDisabledPreferenceController(Context context, - String preferenceKey) { - super(context, preferenceKey); - } - - @Override - public int getAvailabilityStatus() { - if (mManagedUser != null - && isCrossProfileCalendarDisallowedByAdmin( - mContext, mManagedUser.getIdentifier())) { - return AVAILABLE; - } - - return DISABLED_FOR_USER; - } -} diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java index 6591be488a3..f16bc3f49b6 100644 --- a/src/com/android/settings/accounts/ManagedProfileSettings.java +++ b/src/com/android/settings/accounts/ManagedProfileSettings.java @@ -79,7 +79,6 @@ public class ManagedProfileSettings extends DashboardFragment { use(WorkModePreferenceController.class).setManagedUser(mManagedUser); use(ContactSearchPreferenceController.class).setManagedUser(mManagedUser); use(CrossProfileCalendarPreferenceController.class).setManagedUser(mManagedUser); - use(CrossProfileCalendarDisabledPreferenceController.class).setManagedUser(mManagedUser); } @Override diff --git a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java index ff616268063..474a5b6ec79 100644 --- a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java +++ b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java @@ -15,15 +15,25 @@ */ package com.android.settings.applications.specialaccess.interactacrossprofiles; +import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; +import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + import android.Manifest; +import android.annotation.UserIdInt; +import android.app.ActionBar; import android.app.AppOpsManager; +import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.content.PermissionChecker; import android.content.pm.CrossProfileApps; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.UserInfo; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; @@ -32,13 +42,15 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; -import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.preference.Preference; -import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; +import com.android.settings.applications.AppStoreUtil; +import com.android.settings.widget.CardPreference; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.widget.LayoutPreference; public class InteractAcrossProfilesDetails extends AppInfoBase @@ -47,13 +59,21 @@ public class InteractAcrossProfilesDetails extends AppInfoBase private static final String INTERACT_ACROSS_PROFILES_SETTINGS_SWITCH = "interact_across_profiles_settings_switch"; private static final String INTERACT_ACROSS_PROFILES_HEADER = "interact_across_profiles_header"; + public static final String INSTALL_APP_BANNER_KEY = "install_app_banner"; private Context mContext; private CrossProfileApps mCrossProfileApps; private UserManager mUserManager; - private SwitchPreference mSwitchPref; + private RestrictedSwitchPreference mSwitchPref; private LayoutPreference mHeader; + private CardPreference mInstallBanner; private PackageManager mPackageManager; + private UserHandle mPersonalProfile; + private UserHandle mWorkProfile; + private boolean mInstalledInPersonal; + private boolean mInstalledInWork; + private String mAppLabel; + private Intent mInstallAppIntent; @Override public void onCreate(Bundle savedInstanceState) { @@ -64,19 +84,30 @@ public class InteractAcrossProfilesDetails extends AppInfoBase mUserManager = mContext.getSystemService(UserManager.class); mPackageManager = mContext.getPackageManager(); + mWorkProfile = InteractAcrossProfilesSettings.getWorkProfile(mUserManager); + mPersonalProfile = mUserManager.getProfileParent(mWorkProfile); + mInstalledInWork = isPackageInstalled(mPackageName, mWorkProfile.getIdentifier()); + mInstalledInPersonal = isPackageInstalled(mPackageName, mPersonalProfile.getIdentifier()); + + mAppLabel = mPackageInfo.applicationInfo.loadLabel(mPackageManager).toString(); + mInstallAppIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName); + addPreferencesFromResource(R.xml.interact_across_profiles_permissions_details); mSwitchPref = findPreference(INTERACT_ACROSS_PROFILES_SETTINGS_SWITCH); mSwitchPref.setOnPreferenceClickListener(this); + mHeader = findPreference(INTERACT_ACROSS_PROFILES_HEADER); + mInstallBanner = findPreference(INSTALL_APP_BANNER_KEY); + mInstallBanner.setOnPreferenceClickListener(this); + // refreshUi checks that the user can still configure the appOp, return to the // previous page if it can't. if (!refreshUi()) { setIntentAndFinish(true/* appChanged */); } - final UserHandle workProfile = getWorkProfile(); - final UserHandle personalProfile = mUserManager.getProfileParent(workProfile); - addAppTitleAndIcons(personalProfile, workProfile); + addAppTitleAndIcons(mPersonalProfile, mWorkProfile); + styleActionBar(); } private void addAppTitleAndIcons(UserHandle personalProfile, UserHandle workProfile) { @@ -89,70 +120,101 @@ public class InteractAcrossProfilesDetails extends AppInfoBase final ImageView personalIconView = mHeader.findViewById(R.id.entity_header_icon_personal); if (personalIconView != null) { - personalIconView.setImageDrawable(IconDrawableFactory.newInstance(mContext) - .getBadgedIcon(mPackageInfo.applicationInfo, personalProfile.getIdentifier())); + Drawable icon = IconDrawableFactory.newInstance(mContext) + .getBadgedIcon(mPackageInfo.applicationInfo, personalProfile.getIdentifier()) + .mutate(); + if (!mInstalledInPersonal) { + icon.setColorFilter(createSuspendedColorMatrix()); + } + personalIconView.setImageDrawable(icon); } - final ImageView workIconView2 = mHeader.findViewById(R.id.entity_header_icon_work); - if (workIconView2 != null) { - workIconView2.setImageDrawable(IconDrawableFactory.newInstance(mContext) - .getBadgedIcon(mPackageInfo.applicationInfo, workProfile.getIdentifier())); + + final ImageView workIconView = mHeader.findViewById(R.id.entity_header_icon_work); + if (workIconView != null) { + Drawable icon = IconDrawableFactory.newInstance(mContext) + .getBadgedIcon(mPackageInfo.applicationInfo, workProfile.getIdentifier()) + .mutate(); + if (!mInstalledInWork) { + icon.setColorFilter(createSuspendedColorMatrix()); + } + workIconView.setImageDrawable(icon); } } - @Nullable - private UserHandle getWorkProfile() { - for (UserInfo user : mUserManager.getProfiles(UserHandle.myUserId())) { - if (mUserManager.isManagedProfile(user.id)) { - return user.getUserHandle(); - } + private void styleActionBar() { + final ActionBar actionBar = getActivity().getActionBar(); + if (actionBar != null) { + actionBar.setElevation(0); } - return null; + } + + private ColorMatrixColorFilter createSuspendedColorMatrix() { + int grayValue = 127; + float scale = 0.5f; // half bright + + ColorMatrix tempBrightnessMatrix = new ColorMatrix(); + float[] mat = tempBrightnessMatrix.getArray(); + mat[0] = scale; + mat[6] = scale; + mat[12] = scale; + mat[4] = grayValue; + mat[9] = grayValue; + mat[14] = grayValue; + + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0.0f); + matrix.preConcat(tempBrightnessMatrix); + return new ColorMatrixColorFilter(matrix); } @Override public boolean onPreferenceClick(Preference preference) { - if (preference != mSwitchPref) { - return false; - } // refreshUi checks that the user can still configure the appOp, return to the // previous page if it can't. if (!refreshUi()) { setIntentAndFinish(true/* appChanged */); } + if (preference == mSwitchPref) { + handleSwitchPreferenceClick(); + return true; + } + if (preference == mInstallBanner) { + handleInstallBannerClick(); + return true; + } + return false; + } + + private void handleSwitchPreferenceClick() { if (isInteractAcrossProfilesEnabled()) { enableInteractAcrossProfiles(false); refreshUi(); - return true; - } - if (!isInteractAcrossProfilesEnabled()) { + } else { showConsentDialog(); } - return true; } private void showConsentDialog() { - final String appLabel = mPackageInfo.applicationInfo.loadLabel(mPackageManager).toString(); - final View dialogView = getLayoutInflater().inflate( R.layout.interact_across_profiles_consent_dialog, null); final TextView dialogTitle = dialogView.findViewById( R.id.interact_across_profiles_consent_dialog_title); dialogTitle.setText( - getString(R.string.interact_across_profiles_consent_dialog_title, appLabel)); + getString(R.string.interact_across_profiles_consent_dialog_title, mAppLabel)); final TextView dialogSummary = dialogView.findViewById( R.id.interact_across_profiles_consent_dialog_summary); dialogSummary.setText( - getString(R.string.interact_across_profiles_consent_dialog_summary, appLabel)); + getString(R.string.interact_across_profiles_consent_dialog_summary, mAppLabel)); final TextView appDataSummary = dialogView.findViewById(R.id.app_data_summary); appDataSummary.setText(getString( - R.string.interact_across_profiles_consent_dialog_app_data_summary, appLabel)); + R.string.interact_across_profiles_consent_dialog_app_data_summary, mAppLabel)); final TextView permissionsSummary = dialogView.findViewById(R.id.permissions_summary); permissionsSummary.setText(getString( - R.string.interact_across_profiles_consent_dialog_permissions_summary, appLabel)); + R.string.interact_across_profiles_consent_dialog_permissions_summary, mAppLabel)); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setView(dialogView) @@ -171,18 +233,38 @@ public class InteractAcrossProfilesDetails extends AppInfoBase } private boolean isInteractAcrossProfilesEnabled() { - return isInteractAcrossProfilesEnabled( - mContext, mPackageName, mPackageInfo.applicationInfo.uid); + return isInteractAcrossProfilesEnabled(mContext, mPackageName); } - static boolean isInteractAcrossProfilesEnabled(Context context, String packageName, int uid) { + static boolean isInteractAcrossProfilesEnabled( + Context context, String packageName) { + UserManager userManager = context.getSystemService(UserManager.class); + UserHandle workProfile = InteractAcrossProfilesSettings.getWorkProfile(userManager); + UserHandle personalProfile = userManager.getProfileParent(workProfile); + return context.getSystemService( + CrossProfileApps.class).canConfigureInteractAcrossProfiles(packageName) + && isInteractAcrossProfilesEnabledInProfile(context, packageName, personalProfile) + && isInteractAcrossProfilesEnabledInProfile(context, packageName, workProfile); + + } + + private static boolean isInteractAcrossProfilesEnabledInProfile( + Context context, String packageName, UserHandle userHandle) { + final PackageManager packageManager = context.getPackageManager(); + final int uid; + try { + uid = packageManager.getApplicationInfoAsUser( + packageName, /* flags= */0, userHandle).uid; + } catch (PackageManager.NameNotFoundException e) { + return false; + } return PermissionChecker.PERMISSION_GRANTED == PermissionChecker.checkPermissionForPreflight( - context, - Manifest.permission.INTERACT_ACROSS_PROFILES, - PermissionChecker.PID_UNKNOWN, - uid, - packageName); + context, + Manifest.permission.INTERACT_ACROSS_PROFILES, + PermissionChecker.PID_UNKNOWN, + uid, + packageName); } private void enableInteractAcrossProfiles(boolean newState) { @@ -190,14 +272,28 @@ public class InteractAcrossProfilesDetails extends AppInfoBase mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); } + private void handleInstallBannerClick() { + if (mInstallAppIntent == null) { + return; + } + if (!mInstalledInWork) { + mContext.startActivityAsUser(mInstallAppIntent, mWorkProfile); + return; + } + if (!mInstalledInPersonal) { + mContext.startActivityAsUser(mInstallAppIntent, mPersonalProfile); + } + } + /** * @return the summary for the current state of whether the app associated with the given * {@code packageName} is allowed to interact across profiles. */ - public static CharSequence getPreferenceSummary(Context context, String packageName, int uid) { - return context.getString(isInteractAcrossProfilesEnabled(context, packageName, uid) - ? R.string.app_permission_summary_allowed - : R.string.app_permission_summary_not_allowed); + public static CharSequence getPreferenceSummary( + Context context, String packageName) { + return context.getString(isInteractAcrossProfilesEnabled(context, packageName) + ? R.string.interact_across_profiles_summary_allowed + : R.string.interact_across_profiles_summary_not_allowed); } @Override @@ -205,31 +301,99 @@ public class InteractAcrossProfilesDetails extends AppInfoBase if (mPackageInfo == null || mPackageInfo.applicationInfo == null) { return false; } - if (!mCrossProfileApps.canConfigureInteractAcrossProfiles(mPackageName)) { + if (!mCrossProfileApps.canUserAttemptToConfigureInteractAcrossProfiles(mPackageName)) { // Invalid app entry. Should not allow changing permission mSwitchPref.setEnabled(false); return false; } - - final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz); - if (isInteractAcrossProfilesEnabled()) { - mSwitchPref.setChecked(true); - mSwitchPref.setTitle(R.string.interact_across_profiles_switch_enabled); - if (horizontalArrowIcon != null) { - horizontalArrowIcon.setImageDrawable( - mContext.getDrawable(R.drawable.ic_swap_horiz_blue)); - } - } else { - mSwitchPref.setChecked(false); - mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled); - if (horizontalArrowIcon != null) { - horizontalArrowIcon.setImageDrawable( - mContext.getDrawable(R.drawable.ic_swap_horiz_grey)); - } + if (!mCrossProfileApps.canConfigureInteractAcrossProfiles(mPackageName)) { + return refreshUiForNonConfigurableApps(); } + refreshUiForConfigurableApps(); return true; } + private boolean refreshUiForNonConfigurableApps() { + mSwitchPref.setChecked(false); + mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled); + if (!isCrossProfilePackageWhitelisted(mPackageName)) { + mInstallBanner.setVisible(false); + mSwitchPref.setDisabledByAdmin(RestrictedLockUtils.getProfileOrDeviceOwner( + mContext, mWorkProfile)); + return true; + } + mSwitchPref.setEnabled(false); + if (!mInstalledInPersonal && !mInstalledInWork) { + return false; + } + if (!mInstalledInPersonal) { + mInstallBanner.setTitle(getString( + R.string.interact_across_profiles_install_personal_app_title, + mAppLabel)); + mInstallBanner.setSummary( + R.string.interact_across_profiles_install_app_summary); + mInstallBanner.setVisible(true); + return true; + } + if (!mInstalledInWork) { + mInstallBanner.setTitle(getString( + R.string.interact_across_profiles_install_work_app_title, + mAppLabel)); + mInstallBanner.setSummary( + R.string.interact_across_profiles_install_app_summary); + mInstallBanner.setVisible(true); + return true; + } + return false; + } + + private boolean isCrossProfilePackageWhitelisted(String packageName) { + return mContext.getSystemService(DevicePolicyManager.class) + .getAllCrossProfilePackages().contains(packageName); + } + + private boolean isPackageInstalled(String packageName, @UserIdInt int userId) { + final PackageInfo info; + try { + info = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */0) + .getPackageManager().getPackageInfo(packageName, + MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + return info != null; + } + + private void refreshUiForConfigurableApps() { + mInstallBanner.setVisible(false); + mSwitchPref.setEnabled(true); + if (isInteractAcrossProfilesEnabled()) { + enableSwitchPref(); + } else { + disableSwitchPref(); + } + } + + private void enableSwitchPref() { + mSwitchPref.setChecked(true); + mSwitchPref.setTitle(R.string.interact_across_profiles_switch_enabled); + final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz); + if (horizontalArrowIcon != null) { + horizontalArrowIcon.setImageDrawable( + mContext.getDrawable(R.drawable.ic_swap_horiz_blue)); + } + } + + private void disableSwitchPref() { + mSwitchPref.setChecked(false); + mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled); + final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz); + if (horizontalArrowIcon != null) { + horizontalArrowIcon.setImageDrawable( + mContext.getDrawable(R.drawable.ic_swap_horiz_grey)); + } + } + @Override protected AlertDialog createDialog(int id, int errorCode) { return null; diff --git a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsPreferenceController.java b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsPreferenceController.java index 41e25a7d1d0..f57a6ed7c25 100644 --- a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsPreferenceController.java +++ b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsPreferenceController.java @@ -35,7 +35,7 @@ public class InteractAcrossProfilesDetailsPreferenceController @Override public int getAvailabilityStatus() { - return canConfigureInteractAcrossProfiles() ? AVAILABLE : DISABLED_FOR_USER; + return canUserAttemptToConfigureInteractAcrossProfiles() ? AVAILABLE : DISABLED_FOR_USER; } @Override @@ -49,13 +49,12 @@ public class InteractAcrossProfilesDetailsPreferenceController } private CharSequence getPreferenceSummary() { - return InteractAcrossProfilesDetails.getPreferenceSummary(mContext, mPackageName, - mParent.getPackageInfo().applicationInfo.uid); + return InteractAcrossProfilesDetails.getPreferenceSummary(mContext, mPackageName); } - private boolean canConfigureInteractAcrossProfiles() { + private boolean canUserAttemptToConfigureInteractAcrossProfiles() { return mContext.getSystemService(CrossProfileApps.class) - .canConfigureInteractAcrossProfiles(mPackageName); + .canUserAttemptToConfigureInteractAcrossProfiles(mPackageName); } public void setPackageName(String packageName) { diff --git a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettings.java b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettings.java index d686978fde4..c5d848af7a3 100644 --- a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettings.java +++ b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettings.java @@ -85,8 +85,8 @@ public class InteractAcrossProfilesSettings extends EmptyTextSettings { final Preference pref = new AppPreference(prefContext); pref.setIcon(mIconDrawableFactory.getBadgedIcon(appInfo, user.getIdentifier())); pref.setTitle(mPackageManager.getUserBadgedLabel(label, user)); - pref.setSummary(InteractAcrossProfilesDetails.getPreferenceSummary(prefContext, - packageName, appInfo.uid)); + pref.setSummary(InteractAcrossProfilesDetails.getPreferenceSummary( + prefContext, packageName)); pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { @@ -127,49 +127,78 @@ public class InteractAcrossProfilesSettings extends EmptyTextSettings { static ArrayList> collectConfigurableApps( PackageManager packageManager, UserManager userManager, CrossProfileApps crossProfileApps) { - final UserHandle personalProfile = getPersonalProfileForCallingUser(userManager); + final UserHandle workProfile = getWorkProfile(userManager); + if (workProfile == null) { + return new ArrayList<>(); + } + final UserHandle personalProfile = userManager.getProfileParent(workProfile); if (personalProfile == null) { return new ArrayList<>(); } final ArrayList> apps = new ArrayList<>(); - final List installedPackages = packageManager.getInstalledPackagesAsUser( - GET_ACTIVITIES, personalProfile.getIdentifier()); - for (PackageInfo packageInfo : installedPackages) { - if (crossProfileApps.canConfigureInteractAcrossProfiles(packageInfo.packageName)) { + for (PackageInfo packageInfo : getAllInstalledPackages( + packageManager, personalProfile, workProfile)) { + if (crossProfileApps.canUserAttemptToConfigureInteractAcrossProfiles( + packageInfo.packageName)) { apps.add(new Pair<>(packageInfo.applicationInfo, personalProfile)); } } return apps; } + private static List getAllInstalledPackages( + PackageManager packageManager, UserHandle personalProfile, UserHandle workProfile) { + List personalPackages = packageManager.getInstalledPackagesAsUser( + GET_ACTIVITIES, personalProfile.getIdentifier()); + List workPackages = packageManager.getInstalledPackagesAsUser( + GET_ACTIVITIES, workProfile.getIdentifier()); + List allPackages = new ArrayList<>(personalPackages); + for (PackageInfo workPackage : workPackages) { + if (allPackages.stream().noneMatch( + p -> workPackage.packageName.equals(p.packageName))) { + allPackages.add(workPackage); + } + } + return allPackages; + } + /** * @return the number of applications that can interact across profiles. */ static int getNumberOfEnabledApps( Context context, PackageManager packageManager, UserManager userManager, CrossProfileApps crossProfileApps) { + UserHandle workProfile = getWorkProfile(userManager); + if (workProfile == null) { + return 0; + } + UserHandle personalProfile = userManager.getProfileParent(workProfile); + if (personalProfile == null) { + return 0; + } final ArrayList> apps = collectConfigurableApps(packageManager, userManager, crossProfileApps); apps.removeIf( app -> !InteractAcrossProfilesDetails.isInteractAcrossProfilesEnabled( - context, app.first.packageName, app.first.uid)); + context, app.first.packageName) + || !crossProfileApps.canConfigureInteractAcrossProfiles( + app.first.packageName)); return apps.size(); } /** - * Returns the personal profile in the profile group of the calling user. - * Returns null if user is not in a profile group. + * Returns the work profile in the profile group of the calling user. + * Returns null if not found. */ @Nullable - private static UserHandle getPersonalProfileForCallingUser(UserManager userManager) { - final int callingUser = UserHandle.myUserId(); - if (userManager.getProfiles(callingUser).isEmpty()) { - return null; + static UserHandle getWorkProfile(UserManager userManager) { + for (UserInfo user : userManager.getProfiles(UserHandle.myUserId())) { + if (userManager.isManagedProfile(user.id)) { + return user.getUserHandle(); + } } - final UserInfo parentProfile = userManager.getProfileParent(callingUser); - return parentProfile == null - ? UserHandle.of(callingUser) : parentProfile.getUserHandle(); + return null; } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = diff --git a/src/com/android/settings/media/MediaDeviceUpdateWorker.java b/src/com/android/settings/media/MediaDeviceUpdateWorker.java index 281d23e9afb..b800c179859 100644 --- a/src/com/android/settings/media/MediaDeviceUpdateWorker.java +++ b/src/com/android/settings/media/MediaDeviceUpdateWorker.java @@ -151,7 +151,7 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker } MediaDevice getTopDevice() { - return mTopDevice; + return getMediaDeviceById(mTopDevice.getId()); } boolean addDeviceToPlayMedia(MediaDevice device) { diff --git a/src/com/android/settings/network/ims/WifiCallingQueryImsState.java b/src/com/android/settings/network/ims/WifiCallingQueryImsState.java index 6ed0d606590..efa93e5abe5 100644 --- a/src/com/android/settings/network/ims/WifiCallingQueryImsState.java +++ b/src/com/android/settings/network/ims/WifiCallingQueryImsState.java @@ -27,10 +27,6 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; -import com.android.ims.ImsManager; -import com.android.settings.network.SubscriptionUtil; -import com.android.settings.network.telephony.MobileNetworkUtils; - /** * Controller class for querying Wifi calling status */ @@ -66,12 +62,6 @@ public class WifiCallingQueryImsState extends ImsQueryController { return (new ImsQueryWfcUserSetting(subId)).query(); } - @VisibleForTesting - ImsManager getImsManager(int subId) { - return ImsManager.getInstance(mContext, - SubscriptionUtil.getPhoneId(mContext, subId)); - } - /** * Check whether Wifi Calling is a supported feature on this subscription * @@ -107,8 +97,15 @@ public class WifiCallingQueryImsState extends ImsQueryController { if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { return false; } - return isWifiCallingProvisioned() - && MobileNetworkUtils.isImsServiceStateReady(getImsManager(mSubId)); + if (!isWifiCallingProvisioned()) { + return false; + } + try { + return isServiceStateReady(mSubId); + } catch (InterruptedException | IllegalArgumentException | ImsException exception) { + Log.w(LOG_TAG, "fail to get WFC service status. subId=" + mSubId, exception); + } + return false; } /** diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java index 076a87b1774..12b71e87120 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java +++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java @@ -26,8 +26,8 @@ import static com.android.settings.network.telephony.TelephonyConstants.RadioAcc import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA; import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_UNKNOWN; import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA; -import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA; import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO; +import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA; import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO; import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA; @@ -54,7 +54,6 @@ import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsRcsManager; import android.telephony.ims.ProvisioningManager; import android.telephony.ims.RcsUceAdapter; -import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.text.TextUtils; @@ -63,8 +62,6 @@ import android.view.Gravity; import androidx.annotation.VisibleForTesting; -import com.android.ims.ImsException; -import com.android.ims.ImsManager; import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settings.Utils; @@ -150,7 +147,6 @@ public class MobileNetworkUtils { final PhoneAccountHandle simCallManager = context.getSystemService(TelecomManager.class) .getSimCallManagerForSubscription(subId); - final int phoneId = SubscriptionManager.getSlotIndex(subId); boolean isWifiCallingEnabled; if (simCallManager != null) { @@ -161,9 +157,7 @@ public class MobileNetworkUtils { } else { final WifiCallingQueryImsState queryState = new WifiCallingQueryImsState(context, subId); - final ImsManager imsMgr = ImsManager.getInstance(context, phoneId); - isWifiCallingEnabled = queryState.isWifiCallingProvisioned() - && isImsServiceStateReady(imsMgr); + isWifiCallingEnabled = queryState.isReadyToWifiCalling(); } return isWifiCallingEnabled; @@ -280,21 +274,6 @@ public class MobileNetworkUtils { return intent; } - public static boolean isImsServiceStateReady(ImsManager imsMgr) { - boolean isImsServiceStateReady = false; - - try { - if (imsMgr != null && imsMgr.getImsServiceState() == ImsFeature.STATE_READY) { - isImsServiceStateReady = true; - } - } catch (ImsException ex) { - Log.e(TAG, "Exception when trying to get ImsServiceStatus: " + ex); - } - - Log.d(TAG, "isImsServiceStateReady=" + isImsServiceStateReady); - return isImsServiceStateReady; - } - /** * Whether to show the entry point to eUICC settings. * diff --git a/src/com/android/settings/nfc/PaymentDefaultDialog.java b/src/com/android/settings/nfc/PaymentDefaultDialog.java index 73b92e7b6ba..1aa8dca9bd1 100644 --- a/src/com/android/settings/nfc/PaymentDefaultDialog.java +++ b/src/com/android/settings/nfc/PaymentDefaultDialog.java @@ -111,21 +111,23 @@ public final class PaymentDefaultDialog extends AlertActivity implements mNewDefault = component; // Compose dialog; get final AlertController.AlertParams p = mAlertParams; - p.mTitle = getString(R.string.nfc_payment_set_default_label); if (defaultPaymentApp == null) { + p.mTitle = getString(R.string.nfc_payment_set_default_label); String formatString = getString(R.string.nfc_payment_set_default); String msg = String.format(formatString, sanitizePaymentAppCaption(requestedPaymentApp.label.toString())); p.mMessage = msg; + p.mPositiveButtonText = getString(R.string.nfc_payment_btn_text_set_deault); } else { + p.mTitle = getString(R.string.nfc_payment_update_default_label); String formatString = getString(R.string.nfc_payment_set_default_instead_of); String msg = String.format(formatString, sanitizePaymentAppCaption(requestedPaymentApp.label.toString()), sanitizePaymentAppCaption(defaultPaymentApp.label.toString())); p.mMessage = msg; + p.mPositiveButtonText = getString(R.string.nfc_payment_btn_text_update); } - p.mPositiveButtonText = getString(R.string.yes); - p.mNegativeButtonText = getString(R.string.no); + p.mNegativeButtonText = getString(R.string.cancel); p.mPositiveButtonListener = this; p.mNegativeButtonListener = this; setupAlert(); diff --git a/src/com/android/settings/notification/NotificationPeopleStripPreferenceController.java b/src/com/android/settings/notification/NotificationPeopleStripPreferenceController.java deleted file mode 100644 index e16443ec422..00000000000 --- a/src/com/android/settings/notification/NotificationPeopleStripPreferenceController.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2019 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.notification; - - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.provider.Settings; - -import androidx.preference.Preference; -import androidx.preference.PreferenceScreen; - -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settings.core.TogglePreferenceController; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnPause; -import com.android.settingslib.core.lifecycle.events.OnResume; - -import com.google.common.annotations.VisibleForTesting; - -/** Controls toggle setting for people strip in system ui. */ -public class NotificationPeopleStripPreferenceController extends TogglePreferenceController - implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener, - LifecycleObserver, OnResume, OnPause { - - @VisibleForTesting - static final int ON = 1; - @VisibleForTesting - static final int OFF = 0; - - private final Uri mPeopleStripUri = - Settings.Secure.getUriFor(Settings.Secure.PEOPLE_STRIP); - - private Preference mPreference; - private Runnable mUnregisterOnPropertiesChangedListener; - - public NotificationPeopleStripPreferenceController(Context context, String preferenceKey) { - super(context, preferenceKey); - } - - @Override - public void displayPreference(PreferenceScreen screen) { - super.displayPreference(screen); - mPreference = screen.findPreference("notification_people_strip"); - } - - @Override - public void onResume() { - if (mPreference == null) { - return; - } - ContentObserver observer = new ContentObserver(new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - updateState(mPreference); - } - }; - ContentResolver contentResolver = mContext.getContentResolver(); - mUnregisterOnPropertiesChangedListener = - () -> contentResolver.unregisterContentObserver(observer); - contentResolver.registerContentObserver(mPeopleStripUri, false, observer); - } - - @Override - public void onPause() { - if (mUnregisterOnPropertiesChangedListener != null) { - mUnregisterOnPropertiesChangedListener.run(); - mUnregisterOnPropertiesChangedListener = null; - } - } - - @Override - public int getAvailabilityStatus() { - return AVAILABLE; - } - - @Override - public boolean isSliceable() { - return false; - } - - @Override - public boolean isChecked() { - int value = Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.PEOPLE_STRIP, - OFF); - return value != OFF; - } - - @Override - public boolean setChecked(boolean isChecked) { - return Settings.Secure.putInt( - mContext.getContentResolver(), - Settings.Secure.PEOPLE_STRIP, - isChecked ? ON : OFF); - } -} diff --git a/src/com/android/settings/notification/zen/ZenModeCallsSettings.java b/src/com/android/settings/notification/zen/ZenModeCallsSettings.java index 1b5412e0ec8..82d5cf62765 100644 --- a/src/com/android/settings/notification/zen/ZenModeCallsSettings.java +++ b/src/com/android/settings/notification/zen/ZenModeCallsSettings.java @@ -45,6 +45,8 @@ public class ZenModeCallsSettings extends ZenModeSettingsBase { List controllers = new ArrayList<>(); controllers.add(new ZenModePrioritySendersPreferenceController(context, "zen_mode_settings_category_calls", lifecycle, false)); + controllers.add(new ZenModeSendersImagePreferenceController(context, + "zen_mode_calls_image", lifecycle, false)); controllers.add(new ZenModeRepeatCallersPreferenceController(context, lifecycle, context.getResources().getInteger(com.android.internal.R.integer .config_zen_repeat_callers_threshold))); diff --git a/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java b/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java index d15a4aa428b..f8e4548f53f 100644 --- a/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java +++ b/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java @@ -44,6 +44,8 @@ public class ZenModeMessagesSettings extends ZenModeSettingsBase { private static List buildPreferenceControllers(Context context, Lifecycle lifecycle) { List controllers = new ArrayList<>(); + controllers.add(new ZenModeSendersImagePreferenceController(context, + "zen_mode_messages_image", lifecycle, true)); controllers.add(new ZenModePrioritySendersPreferenceController(context, "zen_mode_settings_category_messages", lifecycle, true)); controllers.add(new ZenModeBehaviorFooterPreferenceController( diff --git a/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java b/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java index da7b24d7d33..226ce155af3 100644 --- a/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java +++ b/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java @@ -58,7 +58,7 @@ public class ZenModePrioritySendersPreferenceController @VisibleForTesting static final String KEY_NONE = "senders_none"; private static final Intent ALL_CONTACTS_INTENT = - new Intent(Contacts.Intents.UI.LIST_ALL_CONTACTS_ACTION); + new Intent(Contacts.Intents.UI.LIST_DEFAULT); private static final Intent STARRED_CONTACTS_INTENT = new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION); private static final Intent FALLBACK_INTENT = new Intent(Intent.ACTION_MAIN); diff --git a/src/com/android/settings/notification/zen/ZenModeSendersImagePreferenceController.java b/src/com/android/settings/notification/zen/ZenModeSendersImagePreferenceController.java new file mode 100644 index 00000000000..e8cd40db63a --- /dev/null +++ b/src/com/android/settings/notification/zen/ZenModeSendersImagePreferenceController.java @@ -0,0 +1,108 @@ +/* + * 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.notification.zen; + +import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY; +import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS; +import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED; + +import android.content.Context; +import android.widget.ImageView; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; + +/** + * Common preference controller functionality shared by + * ZenModeCallsSettings and ZenModeMessagesSettings. + * + * Changes the image resource based on the selected senders allowed to bypass DND option for + * calls or messages. + */ +public class ZenModeSendersImagePreferenceController + extends AbstractZenModePreferenceController { + + private final boolean mIsMessages; // if this is false, then this preference is for calls + + private ImageView mImageView; + + public ZenModeSendersImagePreferenceController(Context context, String key, + Lifecycle lifecycle, boolean isMessages) { + super(context, key, lifecycle); + mIsMessages = isMessages; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + LayoutPreference pref = (LayoutPreference) screen.findPreference(KEY); + mImageView = (ImageView) pref.findViewById(R.id.zen_mode_settings_senders_image); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return KEY; + } + + @Override + public void updateState(Preference preference) { + final int currSetting = getPrioritySenders(); + int newImageRes; + CharSequence newContentDescription = ""; + if (PRIORITY_SENDERS_ANY == currSetting) { + newImageRes = mIsMessages + ? R.drawable.zen_messages_any + : R.drawable.zen_calls_any; + newContentDescription = mContext.getString(R.string.zen_mode_from_anyone); + } else if (PRIORITY_SENDERS_CONTACTS == currSetting) { + newImageRes = mIsMessages + ? R.drawable.zen_messages_contacts + : R.drawable.zen_calls_contacts; + newContentDescription = mContext.getString(R.string.zen_mode_from_contacts); + } else if (PRIORITY_SENDERS_STARRED == currSetting) { + newImageRes = mIsMessages + ? R.drawable.zen_messages_starred + : R.drawable.zen_calls_starred; + newContentDescription = mContext.getString(R.string.zen_mode_from_starred); + } else { + newImageRes = mIsMessages + ? R.drawable.zen_messages_none + : R.drawable.zen_calls_none; + newContentDescription = mContext.getString(R.string.zen_mode_from_none); + } + + mImageView.setImageResource(newImageRes); + mImageView.setContentDescription(newContentDescription); + } + + private int getPrioritySenders() { + if (mIsMessages) { + return mBackend.getPriorityMessageSenders(); + } else { + return mBackend.getPriorityCallSenders(); + } + } +} diff --git a/src/com/android/settings/wifi/WifiDialog2.java b/src/com/android/settings/wifi/WifiDialog2.java index acd6f17d36b..dc546f3c231 100644 --- a/src/com/android/settings/wifi/WifiDialog2.java +++ b/src/com/android/settings/wifi/WifiDialog2.java @@ -214,4 +214,8 @@ public class WifiDialog2 extends AlertDialog implements WifiConfigUiBase2, public void setCancelButton(CharSequence text) { setButton(BUTTON_NEGATIVE, text, this); } + + public WifiEntry getWifiEntry() { + return mWifiEntry; + } } diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java index 13ccdc3695b..f73891dfb53 100644 --- a/src/com/android/settings/wifi/WifiSettings2.java +++ b/src/com/android/settings/wifi/WifiSettings2.java @@ -647,6 +647,7 @@ public class WifiSettings2 extends RestrictedSettingsFragment setOffMessage(); setAdditionalSettingsSummaries(); setProgressBarVisible(false); + mClickedConnect = false; break; } } @@ -739,6 +740,11 @@ public class WifiSettings2 extends RestrictedSettingsFragment pref.setOnGearClickListener(preference -> { launchNetworkDetailsFragment(pref); }); + + if (mClickedConnect) { + mClickedConnect = false; + scrollToPreference(mConnectedWifiEntryPreferenceCategory); + } } } else { mConnectedWifiEntryPreferenceCategory.removeAll(); @@ -954,18 +960,30 @@ public class WifiSettings2 extends RestrictedSettingsFragment @Override public void onForget(WifiDialog2 dialog) { - forget(mDialogWifiEntry); + forget(dialog.getWifiEntry()); } @Override public void onSubmit(WifiDialog2 dialog) { - final int dialogMode = mDialog.getController().getMode(); + final int dialogMode = dialog.getMode(); + final WifiConfiguration config = dialog.getController().getConfig(); + final WifiEntry wifiEntry = dialog.getWifiEntry(); if (dialogMode == WifiConfigUiBase2.MODE_MODIFY) { - mWifiManager.save(mDialogWifiEntry.getWifiConfiguration(), mSaveListener); + if (config == null) { + Toast.makeText(getContext(), R.string.wifi_failed_save_message, + Toast.LENGTH_SHORT).show(); + } else { + mWifiManager.save(config, mSaveListener); + } } else if (dialogMode == WifiConfigUiBase2.MODE_CONNECT - || (dialogMode == WifiConfigUiBase2.MODE_VIEW && mDialogWifiEntry.canConnect())) { - connect(mDialogWifiEntry, false /* editIfNoConfig */, false /* fullScreenEdit*/); + || (dialogMode == WifiConfigUiBase2.MODE_VIEW && wifiEntry.canConnect())) { + if (config == null) { + connect(wifiEntry, false /* editIfNoConfig */, + false /* fullScreenEdit*/); + } else { + mWifiManager.connect(config, new WifiConnectActionListener()); + } } } @@ -981,7 +999,8 @@ public class WifiSettings2 extends RestrictedSettingsFragment wifiEntry.forget(null /* callback */); } - private void connect(WifiEntry wifiEntry, boolean editIfNoConfig, boolean fullScreenEdit) { + @VisibleForTesting + void connect(WifiEntry wifiEntry, boolean editIfNoConfig, boolean fullScreenEdit) { mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_WIFI_CONNECT, wifiEntry.isSaved()); @@ -994,7 +1013,7 @@ public class WifiSettings2 extends RestrictedSettingsFragment private class WifiConnectActionListener implements WifiManager.ActionListener { @Override public void onSuccess() { - // Do nothing. + mClickedConnect = true; } @Override @@ -1028,13 +1047,15 @@ public class WifiSettings2 extends RestrictedSettingsFragment return; } - if (status == ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) { + if (status == ConnectCallback.CONNECT_STATUS_SUCCESS) { + mClickedConnect = true; + } else if (status == ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) { if (mEditIfNoConfig) { // Edit an unsaved secure Wi-Fi network. if (mFullScreenEdit) { launchConfigNewNetworkFragment(mConnectWifiEntry); } else { - showDialog(mConnectWifiEntry, WifiConfigUiBase2.MODE_MODIFY); + showDialog(mConnectWifiEntry, WifiConfigUiBase2.MODE_CONNECT); } } } else if (status == CONNECT_STATUS_FAILURE_UNKNOWN) { diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java index 96aae0ea4bb..735fecc9c9a 100644 --- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java +++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java @@ -54,9 +54,7 @@ import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; import com.android.settings.core.SubSettingLauncher; -import com.android.settings.network.SubscriptionUtil; import com.android.settings.network.ims.WifiCallingQueryImsState; -import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.widget.SwitchBar; /** @@ -100,7 +98,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment private boolean mUseWfcHomeModeForRoaming = false; private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - private com.android.ims.ImsManager mImsManager; private ImsMmTelManager mImsMmTelManager; private ProvisioningManager mProvisioningManager; private TelephonyManager mTelephonyManager; @@ -119,8 +116,9 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment queryImsState(WifiCallingSettingsForSub.this.mSubId).isAllowUserControl(); final boolean isWfcEnabled = mSwitchBar.isChecked() && isNonTtyOrTtyOnVolteEnabled; - boolean isCallStateIdle = - mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_IDLE; + boolean isCallStateIdle = getTelephonyManagerForSub( + WifiCallingSettingsForSub.this.mSubId).getCallState() + == TelephonyManager.CALL_STATE_IDLE; mSwitchBar.setEnabled(isCallStateIdle && isNonTtyOrTtyOnVolteEnabled); @@ -201,7 +199,8 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment mSwitchBar.hide(); } - private void showAlert(Intent intent) { + @VisibleForTesting + void showAlert(Intent intent) { final Context context = getActivity(); final CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE); @@ -247,6 +246,14 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment return 0; } + @VisibleForTesting + TelephonyManager getTelephonyManagerForSub(int subId) { + if (mTelephonyManager == null) { + mTelephonyManager = getContext().getSystemService(TelephonyManager.class); + } + return mTelephonyManager.createForSubscriptionId(subId); + } + @VisibleForTesting WifiCallingQueryImsState queryImsState(int subId) { return new WifiCallingQueryImsState(getContext(), subId); @@ -260,12 +267,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment return ProvisioningManager.createForSubscriptionId(mSubId); } - @VisibleForTesting - com.android.ims.ImsManager getImsManager() { - return com.android.ims.ImsManager.getInstance(getActivity(), - SubscriptionUtil.getPhoneId(getActivity(), mSubId)); - } - @VisibleForTesting ImsMmTelManager getImsMmTelManager() { if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { @@ -289,12 +290,9 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment FRAGMENT_BUNDLE_SUBID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); } - mImsManager = getImsManager(); mProvisioningManager = getImsProvisioningManager(); mImsMmTelManager = getImsMmTelManager(); - mTelephonyManager = getActivity().getSystemService(TelephonyManager.class); - mButtonWfcMode = findPreference(BUTTON_WFC_MODE); mButtonWfcMode.setOnPreferenceChangeListener(this); @@ -331,7 +329,7 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment @VisibleForTesting boolean isWfcProvisionedOnDevice() { - return MobileNetworkUtils.isWfcProvisionedOnDevice(mSubId); + return queryImsState(mSubId).isWifiCallingProvisioned(); } private void updateBody() { @@ -420,7 +418,8 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment updateBody(); if (queryImsState(mSubId).isWifiCallingSupported()) { - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + getTelephonyManagerForSub(mSubId).listen(mPhoneStateListener, + PhoneStateListener.LISTEN_CALL_STATE); mSwitchBar.addOnSwitchChangeListener(this); @@ -448,7 +447,8 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment if (mValidListener) { mValidListener = false; - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); + getTelephonyManagerForSub(mSubId).listen(mPhoneStateListener, + PhoneStateListener.LISTEN_NONE); mSwitchBar.removeOnSwitchChangeListener(this); } diff --git a/src/com/android/settings/wifi/calling/WifiCallingSuggestionActivity.java b/src/com/android/settings/wifi/calling/WifiCallingSuggestionActivity.java index 0e3b8872d27..6b6eebfe3a0 100644 --- a/src/com/android/settings/wifi/calling/WifiCallingSuggestionActivity.java +++ b/src/com/android/settings/wifi/calling/WifiCallingSuggestionActivity.java @@ -19,10 +19,8 @@ package com.android.settings.wifi.calling; import android.content.Context; import android.telephony.SubscriptionManager; -import com.android.ims.ImsManager; import com.android.settings.SettingsActivity; import com.android.settings.network.ims.WifiCallingQueryImsState; -import com.android.settings.network.telephony.MobileNetworkUtils; public class WifiCallingSuggestionActivity extends SettingsActivity { @@ -30,11 +28,7 @@ public class WifiCallingSuggestionActivity extends SettingsActivity { final WifiCallingQueryImsState queryState = new WifiCallingQueryImsState(context, SubscriptionManager.getDefaultVoiceSubscriptionId()); - if (!ImsManager.isWfcEnabledByPlatform(context) || - !MobileNetworkUtils.isWfcProvisionedOnDevice( - SubscriptionManager.getDefaultVoiceSubscriptionId())) { - return true; - } - return queryState.isEnabledByUser() && queryState.isAllowUserControl(); + return (!queryState.isWifiCallingProvisioned()) + || (queryState.isEnabledByUser() && queryState.isAllowUserControl()); } } diff --git a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarDisabledPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarDisabledPreferenceControllerTest.java deleted file mode 100644 index 2226e2c4e1d..00000000000 --- a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarDisabledPreferenceControllerTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 - * - * 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.android.settings.core.BasePreferenceController.AVAILABLE; -import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER; - -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.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.robolectric.RuntimeEnvironment.application; - -import android.app.admin.DevicePolicyManager; -import android.content.ComponentName; -import android.content.Context; -import android.os.UserHandle; - -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 org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; -import org.robolectric.shadows.ShadowDevicePolicyManager; - -import java.util.Collections; - -@RunWith(RobolectricTestRunner.class) -public class CrossProfileCalendarDisabledPreferenceControllerTest { - - private static final String PREF_KEY = "cross_profile_calendar_disabled"; - private static final int MANAGED_USER_ID = 10; - private static final String TEST_PACKAGE_NAME = "com.test"; - private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("test", "test"); - - @Mock - private UserHandle mManagedUser; - - private Context mContext; - private CrossProfileCalendarDisabledPreferenceController mController; - private ShadowDevicePolicyManager mDpm; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - mController = new CrossProfileCalendarDisabledPreferenceController(mContext, PREF_KEY); - mController.setManagedUser(mManagedUser); - mDpm = Shadows.shadowOf(application.getSystemService(DevicePolicyManager.class)); - - when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID); - doReturn(mContext).when(mContext).createPackageContextAsUser( - any(String.class), anyInt(), any(UserHandle.class)); - } - - @Test - public void getAvailabilityStatus_noPackageAllowed_shouldBeAvailable() { - mDpm.setProfileOwner(TEST_COMPONENT_NAME); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); - } - - @Test - public void getAvailabilityStatus_somePackagesAllowed_shouldBeDisabledForUser() { - mDpm.setProfileOwner(TEST_COMPONENT_NAME); - mDpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME, - Collections.singleton(TEST_PACKAGE_NAME)); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER); - } - - @Test - public void getAvailabilityStatus_allPackagesAllowed_shouldBeDisabledForUser() { - mDpm.setProfileOwner(TEST_COMPONENT_NAME); - mDpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME, null); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER); - } -} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java index 9e48b9ea3bb..bae9a12670b 100644 --- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java @@ -22,14 +22,18 @@ import static org.robolectric.Shadows.shadowOf; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.CrossProfileApps; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; -import android.os.Process; +import android.content.pm.UserInfo; +import android.os.UserManager; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; +import com.google.common.collect.ImmutableList; + import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -37,6 +41,9 @@ import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) public class InteractAcrossProfilesDetailsTest { + private static final int PERSONAL_PROFILE_ID = 0; + private static final int WORK_PROFILE_ID = 10; + private static final int PACKAGE_UID = 0; private static final String CROSS_PROFILE_PACKAGE_NAME = "crossProfilePackage"; public static final String INTERACT_ACROSS_PROFILES_PERMISSION = "android.permission.INTERACT_ACROSS_PROFILES"; @@ -44,29 +51,53 @@ public class InteractAcrossProfilesDetailsTest { private final Context mContext = ApplicationProvider.getApplicationContext(); private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class); private final PackageManager mPackageManager = mContext.getPackageManager(); - private final InteractAcrossProfilesDetails mFragment = new InteractAcrossProfilesDetails(); + private final UserManager mUserManager = mContext.getSystemService(UserManager.class); + private final CrossProfileApps mCrossProfileApps = mContext.getSystemService( + CrossProfileApps.class); @Test public void getPreferenceSummary_appOpAllowed_returnsAllowed() { + shadowOf(mUserManager).addUser( + PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */); + shadowOf(mUserManager).addProfile( + PERSONAL_PROFILE_ID, WORK_PROFILE_ID, + "work-profile"/* profileName */, UserInfo.FLAG_MANAGED_PROFILE); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + PERSONAL_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME)); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME)); + shadowOf(mCrossProfileApps).addCrossProfilePackage( + CROSS_PROFILE_PACKAGE_NAME); String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION); shadowOf(mAppOpsManager).setMode( - appOp, Process.myUid(), CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED); + appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED); shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo()); - assertThat(mFragment.getPreferenceSummary( - mContext, CROSS_PROFILE_PACKAGE_NAME, Process.myUid())) + assertThat(InteractAcrossProfilesDetails.getPreferenceSummary( + mContext, CROSS_PROFILE_PACKAGE_NAME)) .isEqualTo(mContext.getString(R.string.app_permission_summary_allowed)); } @Test public void getPreferenceSummary_appOpNotAllowed_returnsNotAllowed() { + shadowOf(mUserManager).addUser( + PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */); + shadowOf(mUserManager).addProfile( + PERSONAL_PROFILE_ID, WORK_PROFILE_ID, + "work-profile"/* profileName */, UserInfo.FLAG_MANAGED_PROFILE); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + PERSONAL_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME)); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME)); + shadowOf(mCrossProfileApps).addCrossProfilePackage( + CROSS_PROFILE_PACKAGE_NAME); String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION); shadowOf(mAppOpsManager).setMode( - appOp, Process.myUid(), CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_IGNORED); + appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_IGNORED); shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo()); - assertThat(mFragment.getPreferenceSummary( - mContext, CROSS_PROFILE_PACKAGE_NAME, Process.myUid())) + assertThat(InteractAcrossProfilesDetails.getPreferenceSummary( + mContext, CROSS_PROFILE_PACKAGE_NAME)) .isEqualTo(mContext.getString(R.string.app_permission_summary_not_allowed)); } diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesPreferenceControllerTest.java index bac7437d81d..8479035804b 100644 --- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesPreferenceControllerTest.java @@ -21,12 +21,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.robolectric.Shadows.shadowOf; import android.content.Context; -import android.content.pm.CrossProfileApps; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import androidx.test.core.app.ApplicationProvider; import com.android.settings.core.BasePreferenceController; +import com.google.common.collect.ImmutableList; + import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -36,25 +39,34 @@ public class InteractAcrossProfilesPreferenceControllerTest { private static final String CROSS_PROFILE_PACKAGE_NAME = "crossProfilePackage"; private static final String NOT_CROSS_PROFILE_PACKAGE_NAME = "notCrossProfilePackage"; + public static final String INTERACT_ACROSS_PROFILES_PERMISSION = + "android.permission.INTERACT_ACROSS_PROFILES"; + private static final int PROFILE_ID = 0; private final Context mContext = ApplicationProvider.getApplicationContext(); - private final CrossProfileApps mCrossProfileApps = - mContext.getSystemService(CrossProfileApps.class); + private final PackageManager mPackageManager = mContext.getPackageManager(); private final InteractAcrossProfilesDetailsPreferenceController mController = new InteractAcrossProfilesDetailsPreferenceController(mContext, "test_key"); @Test - public void getAvailabilityStatus_crossProfilePackage_returnsAvailable() { + public void getAvailabilityStatus_requestedCrossProfilePermission_returnsAvailable() { mController.setPackageName(CROSS_PROFILE_PACKAGE_NAME); - shadowOf(mCrossProfileApps).addCrossProfilePackage(CROSS_PROFILE_PACKAGE_NAME); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME)); + PackageInfo packageInfo = shadowOf(mPackageManager).getInternalMutablePackageInfo( + CROSS_PROFILE_PACKAGE_NAME); + packageInfo.requestedPermissions = new String[]{ + INTERACT_ACROSS_PROFILES_PERMISSION}; assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.AVAILABLE); } @Test - public void getAvailabilityStatus_notCrossProfilePackage_returnsDisabled() { + public void getAvailabilityStatus_notRequestedCrossProfilePermission_returnsDisabled() { mController.setPackageName(NOT_CROSS_PROFILE_PACKAGE_NAME); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + PROFILE_ID, ImmutableList.of(NOT_CROSS_PROFILE_PACKAGE_NAME)); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.DISABLED_FOR_USER); diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java index 19ea50b6572..dac3e22913f 100644 --- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java +++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java @@ -18,14 +18,17 @@ package com.android.settings.applications.specialaccess.interactacrossprofiles; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertTrue; import static org.robolectric.Shadows.shadowOf; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.CrossProfileApps; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; +import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.util.Pair; @@ -68,49 +71,56 @@ public class InteractAcrossProfilesSettingsTest { private final CrossProfileApps mCrossProfileApps = mContext.getSystemService(CrossProfileApps.class); private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class); - private final InteractAcrossProfilesSettings mFragment = new InteractAcrossProfilesSettings(); @Test - public void collectConfigurableApps_fromPersonal_returnsPersonalPackages() { + public void collectConfigurableApps_fromPersonal_returnsCombinedPackages() { shadowOf(mUserManager).addUser( PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */); shadowOf(mUserManager).addProfile( PERSONAL_PROFILE_ID, WORK_PROFILE_ID, - "work-profile"/* profileName */, 0/* profileFlags */); + "work-profile"/* profileName */, UserInfo.FLAG_MANAGED_PROFILE); shadowOf(mPackageManager).setInstalledPackagesForUserId( PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES); shadowOf(mPackageManager).setInstalledPackagesForUserId( WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES); - shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE); - shadowOf(mCrossProfileApps).addCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE); + installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE); + installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE); - List> apps = mFragment.collectConfigurableApps( - mPackageManager, mUserManager, mCrossProfileApps); + List> apps = + InteractAcrossProfilesSettings.collectConfigurableApps( + mPackageManager, mUserManager, mCrossProfileApps); - assertThat(apps.size()).isEqualTo(1); - assertThat(apps.get(0).first.packageName).isEqualTo(PERSONAL_CROSS_PROFILE_PACKAGE); + assertThat(apps.size()).isEqualTo(2); + assertTrue(apps.stream().anyMatch( + app -> app.first.packageName.equals(PERSONAL_CROSS_PROFILE_PACKAGE))); + assertTrue(apps.stream().anyMatch( + app -> app.first.packageName.equals(WORK_CROSS_PROFILE_PACKAGE))); } @Test - public void collectConfigurableApps_fromWork_returnsPersonalPackages() { + public void collectConfigurableApps_fromWork_returnsCombinedPackages() { shadowOf(mUserManager).addUser( PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */); shadowOf(mUserManager).addProfile( PERSONAL_PROFILE_ID, WORK_PROFILE_ID, - "work-profile"/* profileName */, 0/* profileFlags */); + "work-profile"/* profileName */, UserInfo.FLAG_MANAGED_PROFILE); ShadowProcess.setUid(WORK_UID); shadowOf(mPackageManager).setInstalledPackagesForUserId( PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES); shadowOf(mPackageManager).setInstalledPackagesForUserId( WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES); - shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE); - shadowOf(mCrossProfileApps).addCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE); + installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE); + installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE); - List> apps = mFragment.collectConfigurableApps( - mPackageManager, mUserManager, mCrossProfileApps); + List> apps = + InteractAcrossProfilesSettings.collectConfigurableApps( + mPackageManager, mUserManager, mCrossProfileApps); - assertThat(apps.size()).isEqualTo(1); - assertThat(apps.get(0).first.packageName).isEqualTo(PERSONAL_CROSS_PROFILE_PACKAGE); + assertThat(apps.size()).isEqualTo(2); + assertTrue(apps.stream().anyMatch( + app -> app.first.packageName.equals(PERSONAL_CROSS_PROFILE_PACKAGE))); + assertTrue(apps.stream().anyMatch( + app -> app.first.packageName.equals(WORK_CROSS_PROFILE_PACKAGE))); } @Test @@ -119,10 +129,11 @@ public class InteractAcrossProfilesSettingsTest { PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */); shadowOf(mPackageManager).setInstalledPackagesForUserId( PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES); - shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE); + installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE); - List> apps = mFragment.collectConfigurableApps( - mPackageManager, mUserManager, mCrossProfileApps); + List> apps = + InteractAcrossProfilesSettings.collectConfigurableApps( + mPackageManager, mUserManager, mCrossProfileApps); assertThat(apps).isEmpty(); } @@ -133,11 +144,14 @@ public class InteractAcrossProfilesSettingsTest { PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */); shadowOf(mUserManager).addProfile( PERSONAL_PROFILE_ID, WORK_PROFILE_ID, - "work-profile"/* profileName */, 0/* profileFlags */); + "work-profile"/* profileName */, UserInfo.FLAG_MANAGED_PROFILE); shadowOf(mPackageManager).setInstalledPackagesForUserId( PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES); + shadowOf(mPackageManager).setInstalledPackagesForUserId( + WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES); + installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE); + installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE); shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE); - shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_NON_CROSS_PROFILE_PACKAGE); String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION); shadowOf(mAppOpsManager).setMode( appOp, PACKAGE_UID, PERSONAL_CROSS_PROFILE_PACKAGE, AppOpsManager.MODE_ALLOWED); @@ -145,12 +159,19 @@ public class InteractAcrossProfilesSettingsTest { appOp, PACKAGE_UID, PERSONAL_NON_CROSS_PROFILE_PACKAGE, AppOpsManager.MODE_IGNORED); shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo()); - int numOfApps = mFragment.getNumberOfEnabledApps( + int numOfApps = InteractAcrossProfilesSettings.getNumberOfEnabledApps( mContext, mPackageManager, mUserManager, mCrossProfileApps); assertThat(numOfApps).isEqualTo(1); } + private void installCrossProfilePackage(int profileId, String packageName) { + PackageInfo personalPackageInfo = shadowOf(mPackageManager).getInternalMutablePackageInfo( + packageName); + personalPackageInfo.requestedPermissions = new String[]{ + INTERACT_ACROSS_PROFILES_PERMISSION}; + } + private PermissionInfo createCrossProfilesPermissionInfo() { PermissionInfo permissionInfo = new PermissionInfo(); permissionInfo.name = INTERACT_ACROSS_PROFILES_PERMISSION; diff --git a/tests/robotests/src/com/android/settings/network/ims/MockWifiCallingQueryImsState.java b/tests/robotests/src/com/android/settings/network/ims/MockWifiCallingQueryImsState.java index af1031da07f..abea839791e 100644 --- a/tests/robotests/src/com/android/settings/network/ims/MockWifiCallingQueryImsState.java +++ b/tests/robotests/src/com/android/settings/network/ims/MockWifiCallingQueryImsState.java @@ -19,9 +19,6 @@ package com.android.settings.network.ims; import android.content.Context; import android.telephony.ims.ImsException; -import com.android.ims.ImsManager; - - /** * Controller class for mock Wifi calling status */ @@ -30,6 +27,7 @@ public class MockWifiCallingQueryImsState extends WifiCallingQueryImsState { private Boolean mIsTtyOnVolteEnabled; private Boolean mIsEnabledOnPlatform; private Boolean mIsProvisionedOnDevice; + private Boolean mIsServiceStateReady; private Boolean mIsEnabledByUser; /** @@ -42,10 +40,6 @@ public class MockWifiCallingQueryImsState extends WifiCallingQueryImsState { super(context, subId); } - public ImsManager getImsManager(int subId) { - return super.getImsManager(subId); - } - public void setIsTtyOnVolteEnabled(boolean enabled) { mIsTtyOnVolteEnabled = enabled; } @@ -84,6 +78,19 @@ public class MockWifiCallingQueryImsState extends WifiCallingQueryImsState { return super.isProvisionedOnDevice(subId); } + public void setServiceStateReady(boolean isReady) { + mIsServiceStateReady = isReady; + } + + @Override + boolean isServiceStateReady(int subId) throws InterruptedException, ImsException, + IllegalArgumentException { + if (mIsServiceStateReady != null) { + return mIsServiceStateReady; + } + return super.isServiceStateReady(subId); + } + public void setIsEnabledByUser(boolean enabled) { mIsEnabledByUser = enabled; } diff --git a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java index b91f7188aef..dbfd3b24766 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java @@ -37,7 +37,6 @@ import android.telephony.ims.ImsMmTelManager; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.ims.ImsManager; import com.android.internal.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.network.ims.MockWifiCallingQueryImsState; @@ -60,8 +59,6 @@ public class WifiCallingPreferenceControllerTest { @Mock private TelephonyManager mTelephonyManager; @Mock - private ImsManager mImsManager; - @Mock private ImsMmTelManager mImsMmTelManager; @Mock private PreferenceScreen mPreferenceScreen; @@ -79,9 +76,8 @@ public class WifiCallingPreferenceControllerTest { mContext = spy(RuntimeEnvironment.application); - mQueryImsState = spy(new MockWifiCallingQueryImsState(mContext, SUB_ID)); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - doReturn(mImsManager).when(mQueryImsState).getImsManager(anyInt()); + mQueryImsState = new MockWifiCallingQueryImsState(mContext, SUB_ID); + mQueryImsState.setIsEnabledByUser(true); mQueryImsState.setIsProvisionedOnDevice(true); mPreference = new Preference(mContext); @@ -109,7 +105,7 @@ public class WifiCallingPreferenceControllerTest { @Test public void updateState_noSimCallManager_setCorrectSummary() { mController.mSimCallManager = null; - doReturn(true).when(mQueryImsState).isEnabledByUser(); + mQueryImsState.setIsEnabledByUser(true); when(mImsMmTelManager.getVoWiFiRoamingModeSetting()).thenReturn( ImsMmTelManager.WIFI_MODE_WIFI_ONLY); when(mImsMmTelManager.getVoWiFiModeSetting()).thenReturn( @@ -149,7 +145,7 @@ public class WifiCallingPreferenceControllerTest { ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED); when(mImsMmTelManager.getVoWiFiModeSetting()).thenReturn( ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED); - doReturn(true).when(mQueryImsState).isEnabledByUser(); + mQueryImsState.setIsEnabledByUser(true); when(mTelephonyManager.isNetworkRoaming()).thenReturn(true); mController.updateState(mPreference); @@ -166,7 +162,7 @@ public class WifiCallingPreferenceControllerTest { ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED); when(mImsMmTelManager.getVoWiFiModeSetting()).thenReturn( ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED); - doReturn(true).when(mQueryImsState).isEnabledByUser(); + mQueryImsState.setIsEnabledByUser(true); when(mTelephonyManager.isNetworkRoaming()).thenReturn(true); mController.updateState(mPreference); diff --git a/tests/robotests/src/com/android/settings/notification/NotificationPeopleStripPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationPeopleStripPreferenceControllerTest.java deleted file mode 100644 index 786ffb37ae7..00000000000 --- a/tests/robotests/src/com/android/settings/notification/NotificationPeopleStripPreferenceControllerTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2019 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.notification; - -import static android.provider.Settings.Secure.PEOPLE_STRIP; - -import static com.android.settings.notification.NotificationPeopleStripPreferenceController.OFF; -import static com.android.settings.notification.NotificationPeopleStripPreferenceController.ON; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.provider.Settings; - -import androidx.preference.Preference; -import androidx.preference.PreferenceScreen; -import androidx.preference.TwoStatePreference; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class NotificationPeopleStripPreferenceControllerTest { - - private static final String KEY_PEOPLE_STRIP = "notification_people_strip"; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private PreferenceScreen mScreen; - - private NotificationPeopleStripPreferenceController mController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - mController = new NotificationPeopleStripPreferenceController(mContext, KEY_PEOPLE_STRIP); - Preference preference = new Preference(RuntimeEnvironment.application); - preference.setKey(mController.getPreferenceKey()); - when(mScreen.findPreference(preference.getKey())).thenReturn(preference); - } - - @Test - public void updateState_preferenceSetCheckedWhenSettingIsOn() { - final TwoStatePreference preference = mock(TwoStatePreference.class); - final Context context = RuntimeEnvironment.application; - Settings.Secure.putInt(context.getContentResolver(), PEOPLE_STRIP, ON); - - mController = new NotificationPeopleStripPreferenceController(context, KEY_PEOPLE_STRIP); - mController.updateState(preference); - - verify(preference).setChecked(true); - } - - @Test - public void updateState_preferenceSetUncheckedWhenSettingIsOff() { - final TwoStatePreference preference = mock(TwoStatePreference.class); - final Context context = RuntimeEnvironment.application; - Settings.Secure.putInt(context.getContentResolver(), PEOPLE_STRIP, OFF); - - mController = new NotificationPeopleStripPreferenceController(context, KEY_PEOPLE_STRIP); - mController.updateState(preference); - - verify(preference).setChecked(false); - } - - @Test - public void isChecked_settingIsOff_shouldReturnFalse() { - Settings.Secure.putInt(mContext.getContentResolver(), PEOPLE_STRIP, OFF); - - assertThat(mController.isChecked()).isFalse(); - } - - @Test - public void isChecked_settingIsOn_shouldReturnTrue() { - Settings.Secure.putInt(mContext.getContentResolver(), PEOPLE_STRIP, ON); - - assertThat(mController.isChecked()).isTrue(); - } - - @Test - public void setChecked_setFalse_disablesSetting() { - Settings.Secure.putInt(mContext.getContentResolver(), PEOPLE_STRIP, ON); - - mController.setChecked(false); - int updatedValue = Settings.Secure.getInt(mContext.getContentResolver(), PEOPLE_STRIP, -1); - - assertThat(updatedValue).isEqualTo(OFF); - } - - @Test - public void setChecked_setTrue_enablesSetting() { - Settings.Secure.putInt(mContext.getContentResolver(), PEOPLE_STRIP, OFF); - - mController.setChecked(true); - int updatedValue = Settings.Secure.getInt(mContext.getContentResolver(), PEOPLE_STRIP, -1); - - assertThat(updatedValue).isEqualTo(ON); - } -} diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java index bd6b20f71d0..b259cc39b4f 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java @@ -15,6 +15,9 @@ */ package com.android.settings.wifi; +import static com.android.settings.wifi.WifiConfigUiBase2.MODE_CONNECT; +import static com.android.settings.wifi.WifiConfigUiBase2.MODE_MODIFY; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -34,6 +37,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.PowerManager; @@ -64,6 +68,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowToast; @RunWith(RobolectricTestRunner.class) public class WifiSettings2Test { @@ -303,4 +308,57 @@ public class WifiSettings2Test { mWifiSettings2.onNumSavedSubscriptionsChanged(); } + + @Test + public void onSubmit_modeModifyNoConfig_toastErrorMessage() { + WifiDialog2 dialog = createWifiDialog2(MODE_MODIFY, null /* config */); + + mWifiSettings2.onSubmit(dialog); + + assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo( + mContext.getString(R.string.wifi_failed_save_message)); + } + + @Test + public void onSubmit_modeModifyHasConfig_saveWifiManager() { + final WifiConfiguration config = mock(WifiConfiguration.class); + WifiDialog2 dialog = createWifiDialog2(MODE_MODIFY, config); + + mWifiSettings2.onSubmit(dialog); + + verify(mWifiManager).save(eq(config), any()); + } + + @Test + public void onSubmit_modeConnectNoConfig_connectWifiEntry() { + WifiDialog2 dialog = createWifiDialog2(MODE_CONNECT, null /* config */); + final WifiEntry wifiEntry = dialog.getWifiEntry(); + + mWifiSettings2.onAttach(mContext); + mWifiSettings2.onSubmit(dialog); + + verify(mWifiSettings2).connect(wifiEntry, false /* editIfNoConfig */, + false /* fullScreenEdit*/); + } + + @Test + public void onSubmit_modeConnectHasConfig_connectWifiManager() { + final WifiConfiguration config = mock(WifiConfiguration.class); + WifiDialog2 dialog = createWifiDialog2(MODE_CONNECT, config); + + mWifiSettings2.onSubmit(dialog); + + verify(mWifiManager).connect(eq(config), any(WifiManager.ActionListener.class)); + } + + private WifiDialog2 createWifiDialog2(int mode, WifiConfiguration config) { + final WifiEntry wifiEntry = mock(WifiEntry.class); + when(wifiEntry.canConnect()).thenReturn(true); + final WifiConfigController2 controller = mock(WifiConfigController2.class); + when(controller.getConfig()).thenReturn(config); + final WifiDialog2 wifiDialog2 = spy(WifiDialog2.createModal(mContext, null /* listener */, + wifiEntry, mode)); + when(wifiDialog2.getController()).thenReturn(controller); + return wifiDialog2; + } } diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java index 5b76adc84c5..2e93faac27e 100644 --- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java +++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java @@ -50,16 +50,15 @@ import android.widget.TextView; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.ims.ImsConfig; -import com.android.ims.ImsManager; import com.android.settings.R; import com.android.settings.SettingsActivity; +import com.android.settings.network.ims.MockWifiCallingQueryImsState; +import com.android.settings.network.ims.WifiCallingQueryImsState; import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settings.widget.SwitchBar; import com.android.settings.widget.ToggleSwitch; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -73,6 +72,8 @@ import org.robolectric.util.ReflectionHelpers; @Config(shadows = ShadowFragment.class) @RunWith(RobolectricTestRunner.class) public class WifiCallingSettingsForSubTest { + private static final int SUB_ID = 2; + private static final String BUTTON_WFC_MODE = "wifi_calling_mode"; private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode"; private static final String TEST_EMERGENCY_ADDRESS_CARRIER_APP = @@ -83,9 +84,10 @@ public class WifiCallingSettingsForSubTest { private TextView mEmptyView; private final PersistableBundle mBundle = new PersistableBundle(); + private MockWifiCallingQueryImsState mQueryImsState; + @Mock private static CarrierConfigManager sCarrierConfigManager; @Mock private CarrierConfigManager mMockConfigManager; - @Mock private ImsManager mImsManager; @Mock private ImsMmTelManager mImsMmTelManager; @Mock private TelephonyManager mTelephonyManager; @Mock private PreferenceScreen mPreferenceScreen; @@ -93,7 +95,6 @@ public class WifiCallingSettingsForSubTest { @Mock private SwitchBar mSwitchBar; @Mock private ToggleSwitch mToggleSwitch; @Mock private View mView; - @Mock private ImsConfig mImsConfig; @Mock private ListWithEntrySummaryPreference mButtonWfcMode; @Mock private ListWithEntrySummaryPreference mButtonWfcRoamingMode; @Mock private Preference mUpdateAddress; @@ -127,12 +128,13 @@ public class WifiCallingSettingsForSubTest { ReflectionHelpers.setField(mSwitchBar, "mSwitch", mToggleSwitch); doReturn(mSwitchBar).when(mView).findViewById(R.id.switch_bar); - doReturn(mImsManager).when(mFragment).getImsManager(); + mQueryImsState = new MockWifiCallingQueryImsState(mContext, SUB_ID); + doReturn(mImsMmTelManager).when(mFragment).getImsMmTelManager(); - doReturn(mImsConfig).when(mImsManager).getConfigInterface(); - doReturn(true).when(mFragment).isWfcProvisionedOnDevice(); - doReturn(true).when(mImsManager).isWfcEnabledByUser(); - doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled(); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByPlatform(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); doReturn(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED) .when(mImsMmTelManager).getVoWiFiModeSetting(); doReturn(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED) @@ -178,7 +180,7 @@ public class WifiCallingSettingsForSubTest { @Test public void onResume_provisioningDisallowed_shouldFinish() { // Call onResume while provisioning is disallowed. - doReturn(false).when(mFragment).isWfcProvisionedOnDevice(); + mQueryImsState.setIsProvisionedOnDevice(false); mFragment.onResume(); // Verify that finish() is called @@ -197,7 +199,6 @@ public class WifiCallingSettingsForSubTest { } @Test - @Ignore public void onResume_useWfcHomeModeConfigFalseAndEditable_shouldShowWfcRoaming() { // Call onResume to update the WFC roaming preference. mFragment.onResume(); @@ -351,5 +352,18 @@ public class WifiCallingSettingsForSubTest { return null; } } + + @Override + TelephonyManager getTelephonyManagerForSub(int subId) { + return mTelephonyManager; + } + + @Override + WifiCallingQueryImsState queryImsState(int subId) { + return mQueryImsState; + } + + @Override + void showAlert(Intent intent) {} } } diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsTest.java index 90633cb8d6b..1ba8e7a44fa 100644 --- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsTest.java +++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsTest.java @@ -18,7 +18,6 @@ package com.android.settings.wifi.calling; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -72,12 +71,10 @@ public class WifiCallingSettingsTest { mContext = spy(RuntimeEnvironment.application); - mQueryImsState1 = spy(new MockWifiCallingQueryImsState(mContext, SUB_ID1)); - mQueryImsState2 = spy(new MockWifiCallingQueryImsState(mContext, SUB_ID2)); - doReturn(true).when(mQueryImsState1).isEnabledByUser(); - doReturn(true).when(mQueryImsState2).isEnabledByUser(); - doReturn(mImsManager).when(mQueryImsState1).getImsManager(anyInt()); - doReturn(mImsManager).when(mQueryImsState2).getImsManager(anyInt()); + mQueryImsState1 = new MockWifiCallingQueryImsState(mContext, SUB_ID1); + mQueryImsState2 = new MockWifiCallingQueryImsState(mContext, SUB_ID2); + mQueryImsState1.setIsEnabledByUser(true); + mQueryImsState2.setIsEnabledByUser(true); mQueryImsState1.setIsEnabledByPlatform(true); mQueryImsState2.setIsEnabledByPlatform(true); mQueryImsState1.setIsProvisionedOnDevice(true); diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java index f537be32c3e..0013234c950 100644 --- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java +++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java @@ -47,7 +47,7 @@ import androidx.slice.widget.SliceLiveData; import com.android.ims.ImsManager; import com.android.settings.R; -import com.android.settings.network.ims.WifiCallingQueryImsState; +import com.android.settings.network.ims.MockWifiCallingQueryImsState; import com.android.settings.slices.CustomSliceRegistry; import com.android.settings.slices.SettingsSliceProvider; import com.android.settings.slices.SliceBroadcastReceiver; @@ -81,7 +81,7 @@ public class WifiCallingSliceHelperTest { @Mock private ImsMmTelManager mMockImsMmTelManager; - private WifiCallingQueryImsState mQueryImsState; + private MockWifiCallingQueryImsState mQueryImsState; private FakeWifiCallingSliceHelper mWfcSliceHelper; private SettingsSliceProvider mProvider; @@ -105,9 +105,10 @@ public class WifiCallingSliceHelperTest { mFeatureFactory = FakeFeatureFactory.setupForTest(); mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider(); - mQueryImsState = spy(new WifiCallingQueryImsState(mContext, SUB_ID)); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); + mQueryImsState = new MockWifiCallingQueryImsState(mContext, SUB_ID); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsEnabledByPlatform(true); + mQueryImsState.setIsProvisionedOnDevice(true); mWfcSliceHelper = spy(new FakeWifiCallingSliceHelper(mContext)); doReturn(mQueryImsState).when(mWfcSliceHelper).queryImsState(anyInt()); @@ -118,8 +119,8 @@ public class WifiCallingSliceHelperTest { @Test public void test_CreateWifiCallingSlice_invalidSubId() { - doReturn(true).when(mQueryImsState).isEnabledByUser(); - doReturn(false).when(mQueryImsState).isWifiCallingProvisioned(); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsProvisionedOnDevice(false); mWfcSliceHelper.setDefaultVoiceSubId(-1); final Slice slice = mWfcSliceHelper.createWifiCallingSlice( @@ -130,7 +131,7 @@ public class WifiCallingSliceHelperTest { @Test public void test_CreateWifiCallingSlice_wfcNotSupported() { - doReturn(false).when(mQueryImsState).isWifiCallingProvisioned(); + mQueryImsState.setIsProvisionedOnDevice(false); final Slice slice = mWfcSliceHelper.createWifiCallingSlice( CustomSliceRegistry.WIFI_CALLING_URI); @@ -146,9 +147,9 @@ public class WifiCallingSliceHelperTest { turned off) we need to guide the user to wifi calling settings activity so the user can perform the activation there.(PrimaryAction) */ - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(false).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(false); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(false); + mQueryImsState.setIsTtyOnVolteEnabled(false); when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); mWfcSliceHelper.setActivationAppIntent(new Intent()); // dummy Intent @@ -163,9 +164,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_CreateWifiCallingSlice_success() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); final Slice slice = mWfcSliceHelper.createWifiCallingSlice( @@ -177,9 +178,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_SettingSliceProvider_getsRightSliceWifiCalling() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) .thenReturn(mWfcSliceHelper); @@ -192,9 +193,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_SliceBroadcastReceiver_toggleOnWifiCalling() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(false).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(false); + mQueryImsState.setIsTtyOnVolteEnabled(true); when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) .thenReturn(mWfcSliceHelper); mWfcSliceHelper.setActivationAppIntent(null); @@ -216,9 +217,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_CreateWifiCallingPreferenceSlice_prefNotEditable() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); mWfcSliceHelper.setIsWifiCallingPrefEditable(false); final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice( @@ -230,9 +231,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_CreateWifiCallingPreferenceSlice_wfcOff() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(false).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(false); + mQueryImsState.setIsTtyOnVolteEnabled(true); mWfcSliceHelper.setIsWifiCallingPrefEditable(true); final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice( @@ -246,9 +247,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_CreateWifiCallingPreferenceSlice_success() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); when(mMockImsMmTelManager.getVoWiFiModeSetting()).thenReturn( ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED); mWfcSliceHelper.setIsWifiCallingPrefEditable(true); @@ -263,9 +264,9 @@ public class WifiCallingSliceHelperTest { @Test public void test_SettingsSliceProvider_getWfcPreferenceSlice() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); when(mMockImsMmTelManager.getVoWiFiModeSetting()).thenReturn( ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED); when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) @@ -281,9 +282,9 @@ public class WifiCallingSliceHelperTest { } @Test public void test_SliceBroadcastReceiver_setWfcPrefCellularPref() { - doReturn(true).when(mQueryImsState).isWifiCallingProvisioned(); - doReturn(true).when(mQueryImsState).isEnabledByUser(); - when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); when(mMockImsMmTelManager.getVoWiFiModeSetting()).thenReturn( ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED); when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext)) @@ -447,14 +448,6 @@ public class WifiCallingSliceHelperTest { mSubId = id; } - boolean isWfcProvisionedOnDevice(int subId) { - return true; - } - - WifiCallingQueryImsState queryImsState(int subId) { - return super.queryImsState(subId); - } - @Override protected Intent getWifiCallingCarrierActivityIntent(int subId) { return mActivationAppIntent; diff --git a/tests/uitests/assets/search_results_list b/tests/uitests/assets/search_results_list index a6dafe2e98e..f8694636767 100644 --- a/tests/uitests/assets/search_results_list +++ b/tests/uitests/assets/search_results_list @@ -150,7 +150,6 @@ Cool color temperature;color_temperature Copyright;copyright Correction mode;type Cross-profile calendar;cross_profile_calendar -Cross-profile calendar;cross_profile_calendar_disabled Current screen saver;current_screensaver Custom;zen_custom Custom restrictions;zen_mode_block_settings_page