diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 9c6b97aa2a3..8e3378a2610 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1423,8 +1423,7 @@ + android:noHistory="true"> @@ -1494,7 +1493,6 @@ @@ -1506,8 +1504,7 @@ + android:exported="true"> @@ -1864,8 +1861,7 @@ + android:label="@string/usage_access_title"> diff --git a/libs/window_ext_lib.aar b/libs/window_ext_lib.aar index ca58b362099..d34afbda298 100644 Binary files a/libs/window_ext_lib.aar and b/libs/window_ext_lib.aar differ diff --git a/res/values/config.xml b/res/values/config.xml index 48d698cc465..0065a651b2f 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -560,4 +560,7 @@ false + + + false diff --git a/res/values/strings.xml b/res/values/strings.xml index 6240175fbdd..ba8f06d249f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13366,7 +13366,7 @@ Allow access to wallet from lock screen and quick settings - Show QR Scanner + Show QR scanner Allow access to QR scanner from lock screen @@ -13549,6 +13549,8 @@ You won\’t have access to data or the internet through %s. Internet will only be available via Wi\u2011Fi. your carrier + + Not allowed by your organization Unavailable because bedtime mode is on diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java index ac3a01df8cf..ab999ed8888 100644 --- a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java @@ -16,10 +16,7 @@ package com.android.settings.activityembedding; -import android.app.Activity; -import android.app.ActivityTaskManager; import android.content.Context; -import android.graphics.Rect; import android.util.DisplayMetrics; import android.util.FeatureFlagUtils; import android.util.Log; @@ -65,13 +62,4 @@ public class ActivityEmbeddingUtils { return isFlagEnabled && isSplitSupported; } - - /** Whether the screen meets two-pane resolution. */ - public static boolean isTwoPaneResolution(Activity activity) { - final Rect currentTaskBounds = - ActivityTaskManager.getInstance().getTaskBounds(activity.getTaskId()); - - return currentTaskBounds.width() >= getMinCurrentScreenSplitWidthPx(activity) - && currentTaskBounds.height() >= getMinSmallestScreenSplitWidthPx(activity); - } } diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 183a2fbf5f5..c56d89b1a3a 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -42,6 +42,7 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.window.embedding.SplitController; import androidx.window.embedding.SplitRule; import com.android.settings.R; @@ -85,8 +86,9 @@ public class SettingsHomepageActivity extends FragmentActivity implements private View mTwoPaneSuggestionView; private CategoryMixin mCategoryMixin; private Set mLoadedListeners; + private SplitController mSplitController; private boolean mIsEmbeddingActivityEnabled; - private boolean mIsTwoPaneLastTime; + private boolean mIsTwoPane; /** A listener receiving homepage loaded events. */ public interface HomepageLoadedListener { @@ -149,7 +151,8 @@ public class SettingsHomepageActivity extends FragmentActivity implements super.onCreate(savedInstanceState); setContentView(R.layout.settings_homepage_container); mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this); - mIsTwoPaneLastTime = ActivityEmbeddingUtils.isTwoPaneResolution(this); + mSplitController = SplitController.getInstance(); + mIsTwoPane = mSplitController.isActivityEmbedded(this); final View appBar = findViewById(R.id.app_bar_container); appBar.setMinimumHeight(getSearchBoxHeight()); @@ -213,9 +216,9 @@ public class SettingsHomepageActivity extends FragmentActivity implements @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - final boolean isTwoPane = ActivityEmbeddingUtils.isTwoPaneResolution(this); - if (mIsTwoPaneLastTime != isTwoPane) { - mIsTwoPaneLastTime = isTwoPane; + final boolean newTwoPaneState = mSplitController.isActivityEmbedded(this); + if (mIsTwoPane != newTwoPaneState) { + mIsTwoPane = newTwoPaneState; updateHomepageAppBar(); updateHomepageBackground(); } @@ -254,7 +257,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements } final Window window = getWindow(); - final int color = ActivityEmbeddingUtils.isTwoPaneResolution(this) + final int color = mIsTwoPane ? Utils.getColorAttrDefaultColor(this, com.android.internal.R.attr.colorSurface) : Utils.getColorAttrDefaultColor(this, android.R.attr.colorBackground); @@ -416,7 +419,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements if (!mIsEmbeddingActivityEnabled) { return; } - if (ActivityEmbeddingUtils.isTwoPaneResolution(this)) { + if (mIsTwoPane) { findViewById(R.id.homepage_app_bar_regular_phone_view).setVisibility(View.GONE); findViewById(R.id.homepage_app_bar_two_pane_view).setVisibility(View.VISIBLE); } else { diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java index f76a3de85d7..7ce673074ee 100644 --- a/src/com/android/settings/homepage/TopLevelSettings.java +++ b/src/com/android/settings/homepage/TopLevelSettings.java @@ -33,6 +33,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; +import androidx.window.embedding.SplitController; import com.android.settings.R; import com.android.settings.Utils; @@ -144,7 +145,7 @@ public class TopLevelSettings extends DashboardFragment implements if (mFirstStarted) { mFirstStarted = false; } else if (mIsEmbeddingActivityEnabled && isOnlyOneActivityInTask() - && !ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) { + && !SplitController.getInstance().isActivityEmbedded(getActivity())) { // Set default highlight menu key for 1-pane homepage since it will show the placeholder // page once changing back to 2-pane. Log.i(TAG, "Set default menu key"); diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java index cc0e8a153b7..c2aeeaf8133 100644 --- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java +++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java @@ -22,6 +22,7 @@ import android.content.Context; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.notification.LockScreenNotificationPreferenceController; +import com.android.settings.safetycenter.SafetyCenterStatus; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -89,5 +90,10 @@ public class PrivacyDashboardFragment extends DashboardFragment { Context context) { return buildPreferenceControllers(context, null); } + + @Override + protected boolean isPageSearchEnabled(Context context) { + return !SafetyCenterStatus.isEnabled(); + } }; } diff --git a/src/com/android/settings/users/UserCapabilities.java b/src/com/android/settings/users/UserCapabilities.java index 7af6c645f66..620738f1386 100644 --- a/src/com/android/settings/users/UserCapabilities.java +++ b/src/com/android/settings/users/UserCapabilities.java @@ -23,6 +23,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import com.android.settings.R; import com.android.settings.Utils; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; @@ -30,7 +31,7 @@ import com.android.settingslib.RestrictedLockUtilsInternal; public class UserCapabilities { boolean mEnabled = true; boolean mCanAddUser = true; - boolean mCanAddRestrictedProfile = true; + boolean mCanAddRestrictedProfile; boolean mIsAdmin; boolean mIsGuest; boolean mUserSwitcherEnabled; @@ -57,12 +58,13 @@ public class UserCapabilities { caps.mIsAdmin = myUserInfo.isAdmin(); DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( Context.DEVICE_POLICY_SERVICE); - // No restricted profiles for tablets with a device owner, or phones. - if (dpm.isDeviceManaged() - || Utils.isVoiceCapable(context) - || !userManager.isUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED)) { - caps.mCanAddRestrictedProfile = false; - } + + boolean offerRestricted = + context.getResources().getBoolean(R.bool.config_offer_restricted_profiles); + caps.mCanAddRestrictedProfile = + offerRestricted && !dpm.isDeviceManaged() && userManager.isUserTypeEnabled( + UserManager.USER_TYPE_FULL_RESTRICTED); + caps.updateAddUserCapabilities(context); return caps; } diff --git a/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java b/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java index ff8f805b5e8..ddd57f3a76d 100644 --- a/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java +++ b/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java @@ -31,10 +31,10 @@ import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceGroupAdapter; import androidx.preference.PreferenceViewHolder; import androidx.recyclerview.widget.RecyclerView; +import androidx.window.embedding.SplitController; import com.android.settings.R; import com.android.settings.Utils; -import com.android.settings.activityembedding.ActivityEmbeddingUtils; import com.android.settings.homepage.SettingsHomepageActivity; /** @@ -255,6 +255,6 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt } private boolean isHighlightNeeded() { - return ActivityEmbeddingUtils.isTwoPaneResolution(mHomepageActivity); + return SplitController.getInstance().isActivityEmbedded(mHomepageActivity); } } diff --git a/src/com/android/settings/wifi/AddWifiNetworkPreference.java b/src/com/android/settings/wifi/AddWifiNetworkPreference.java index ff4d38e6fde..18205391525 100644 --- a/src/com/android/settings/wifi/AddWifiNetworkPreference.java +++ b/src/com/android/settings/wifi/AddWifiNetworkPreference.java @@ -26,8 +26,10 @@ import androidx.annotation.DrawableRes; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.wifi.dpp.WifiDppUtils; +import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils; /** * The Preference for users to add Wi-Fi networks in WifiSettings @@ -37,6 +39,8 @@ public class AddWifiNetworkPreference extends Preference { private static final String TAG = "AddWifiNetworkPreference"; private final Drawable mScanIconDrawable; + @VisibleForTesting + boolean mIsAddWifiConfigAllow; public AddWifiNetworkPreference(Context context) { super(context); @@ -47,6 +51,8 @@ public class AddWifiNetworkPreference extends Preference { setTitle(R.string.wifi_add_network); mScanIconDrawable = getDrawable(R.drawable.ic_scan_24dp); + mIsAddWifiConfigAllow = WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(context); + updatePreferenceForRestriction(); } @Override @@ -73,4 +79,12 @@ public class AddWifiNetworkPreference extends Preference { } return buttonIcon; } + + @VisibleForTesting + void updatePreferenceForRestriction() { + if (!mIsAddWifiConfigAllow) { + setEnabled(false); + setSummary(R.string.not_allowed_by_ent); + } + } } diff --git a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java index 6bf91040443..f1e656851d5 100644 --- a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java +++ b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java @@ -36,6 +36,7 @@ import androidx.fragment.app.FragmentManager; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin; +import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils; /** * When apps send a new intent with a WifiConfiguration list extra to Settings APP. Settings APP @@ -55,6 +56,8 @@ public class AddAppNetworksActivity extends FragmentActivity { final Bundle mBundle = new Bundle(); @VisibleForTesting IActivityManager mActivityManager = ActivityManager.getService(); + @VisibleForTesting + boolean mIsAddWifiConfigAllow; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -71,6 +74,8 @@ public class AddAppNetworksActivity extends FragmentActivity { window.setGravity(Gravity.BOTTOM); window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT); + + mIsAddWifiConfigAllow = WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(this); } @Override @@ -85,6 +90,10 @@ public class AddAppNetworksActivity extends FragmentActivity { @VisibleForTesting protected boolean showAddNetworksFragment() { + if (!mIsAddWifiConfigAllow) { + Log.d(TAG, "Not allowed by Enterprise Restriction"); + return false; + } String packageName = getCallingAppPackageName(); if (TextUtils.isEmpty(packageName)) { Log.d(TAG, "Package name is null"); diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java index 1d4f2019fb8..dc42515bf90 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java @@ -49,6 +49,7 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager private final Map> mRestrictionSources = new HashMap<>(); private final List mUserProfileInfos = new ArrayList<>(); private final Set mManagedProfiles = new HashSet<>(); + private final Set mEnabledTypes = new HashSet<>(); private boolean mIsQuietModeEnabled = false; private int[] profileIdsForUser = new int[0]; private boolean mUserSwitchEnabled; @@ -105,6 +106,11 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager mGuestRestrictions.add(restriction); } + @Implementation + protected boolean hasUserRestriction(String restrictionKey) { + return hasUserRestriction(restrictionKey, UserHandle.of(UserHandle.myUserId())); + } + public static ShadowUserManager getShadow() { return (ShadowUserManager) Shadow.extract( RuntimeEnvironment.application.getSystemService(UserManager.class)); @@ -199,4 +205,17 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager public void setSwitchabilityStatus(@UserManager.UserSwitchabilityResult int newStatus) { mSwitchabilityStatus = newStatus; } + + @Implementation + protected boolean isUserTypeEnabled(String userType) { + return mEnabledTypes.contains(userType); + } + + public void setUserTypeEnabled(String type, boolean enabled) { + if (enabled) { + mEnabledTypes.add(type); + } else { + mEnabledTypes.remove(type); + } + } } diff --git a/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java index 382ac5d364e..628c14e5051 100644 --- a/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java +++ b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java @@ -18,12 +18,17 @@ package com.android.settings.users; import static com.google.common.truth.Truth.assertThat; +import android.content.ComponentName; import android.content.Context; import android.os.UserHandle; import android.os.UserManager; +import com.android.settings.R; +import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowUserManager; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,16 +37,24 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowUserManager.class}) +@Config(shadows = {ShadowUserManager.class, ShadowDevicePolicyManager.class, + SettingsShadowResources.class}) public class UserCapabilitiesTest { private Context mContext; private ShadowUserManager mUserManager; + private ShadowDevicePolicyManager mDpm; @Before public void setUp() { mContext = RuntimeEnvironment.application; mUserManager = ShadowUserManager.getShadow(); + mDpm = ShadowDevicePolicyManager.getShadow(); + } + + @After + public void tearDown() { + SettingsShadowResources.reset(); } @Test @@ -85,4 +98,40 @@ public class UserCapabilitiesTest { assertThat(userCapabilities.mUserSwitcherEnabled).isTrue(); } + + @Test + public void restrictedProfile_enabled() { + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED, true); + mDpm.setDeviceOwner(null); + SettingsShadowResources.overrideResource(R.bool.config_offer_restricted_profiles, true); + final UserCapabilities userCapabilities = UserCapabilities.create(mContext); + assertThat(userCapabilities.mCanAddRestrictedProfile).isTrue(); + } + + @Test + public void restrictedProfile_configNotSet() { + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED, true); + mDpm.setDeviceOwner(null); + SettingsShadowResources.overrideResource(R.bool.config_offer_restricted_profiles, false); + final UserCapabilities userCapabilities = UserCapabilities.create(mContext); + assertThat(userCapabilities.mCanAddRestrictedProfile).isFalse(); + } + + @Test + public void restrictedProfile_deviceIsManaged() { + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED, true); + mDpm.setDeviceOwner(new ComponentName("test", "test")); + SettingsShadowResources.overrideResource(R.bool.config_offer_restricted_profiles, true); + final UserCapabilities userCapabilities = UserCapabilities.create(mContext); + assertThat(userCapabilities.mCanAddRestrictedProfile).isFalse(); + } + + @Test + public void restrictedProfile_typeNotEnabled() { + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED, false); + mDpm.setDeviceOwner(null); + SettingsShadowResources.overrideResource(R.bool.config_offer_restricted_profiles, true); + final UserCapabilities userCapabilities = UserCapabilities.create(mContext); + assertThat(userCapabilities.mCanAddRestrictedProfile).isFalse(); + } } diff --git a/tests/robotests/src/com/android/settings/wifi/AddWifiNetworkPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/AddWifiNetworkPreferenceTest.java new file mode 100644 index 00000000000..04ecdabf9fb --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/AddWifiNetworkPreferenceTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 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.wifi; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserManager; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +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; + +@RunWith(RobolectricTestRunner.class) +public class AddWifiNetworkPreferenceTest { + + private Context mContext; + private AddWifiNetworkPreference mPreference; + + @Mock + private UserManager mUserManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + mPreference = new AddWifiNetworkPreference(mContext); + + } + + @Test + public void updatePreferenceForRestriction_isAddWifiConfigAllowed_prefIsEnabled() { + mPreference.mIsAddWifiConfigAllow = true; + + mPreference.updatePreferenceForRestriction(); + + assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + } + + @Test + public void updatePreferenceForRestriction_isAddWifiConfigNotAllowed_prefIsDisabled() { + mPreference.mIsAddWifiConfigAllow = false; + + mPreference.updatePreferenceForRestriction(); + + assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getString(R.string.not_allowed_by_ent)); + } +} diff --git a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivityTest.java b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivityTest.java index 39408e2fc9c..6cd20fc26fb 100644 --- a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivityTest.java +++ b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivityTest.java @@ -47,6 +47,7 @@ public class AddAppNetworksActivityTest { mActivity = Robolectric.buildActivity(AddAppNetworksActivity.class).create().get(); mActivity.mActivityManager = mIActivityManager; + mActivity.mIsAddWifiConfigAllow = true; } @Test @@ -77,6 +78,13 @@ public class AddAppNetworksActivityTest { assertThat(mActivity.showAddNetworksFragment()).isTrue(); } + @Test + public void showAddNetworksFragment_isAddWifiConfigNotAllow_returnFalse() { + mActivity.mIsAddWifiConfigAllow = false; + + assertThat(mActivity.showAddNetworksFragment()).isFalse(); + } + private void fakeCallingPackage(@Nullable String packageName) { try { when(mIActivityManager.getLaunchedFromPackage(any())).thenReturn(packageName);