From f7811dfd09374a2dbae3f1268a726a47e5595ef0 Mon Sep 17 00:00:00 2001 From: tom hsu Date: Thu, 3 Jun 2021 11:46:30 +0800 Subject: [PATCH 01/14] [Settings] Disable gear button if user is not admin. - Mobile settings include many settings which second user shall not modify, so make gear button disabled to avoid second user want to try. Bug: 184303943 Test: Maunal test passeded Test: atest passed. Change-Id: Ic04fa71772df4ac424965ad2ca95733b1e15d6a7 --- .../SubscriptionsPreferenceController.java | 12 ++- .../settings/widget/GearPreference.java | 16 +++- .../widget/MutableGearPreference.java | 57 +++++++++++++ ...SubscriptionsPreferenceControllerTest.java | 5 ++ .../settings/widget/GearPreferenceTest.java | 84 +++++++++++++++++++ .../widget/MutableGearPreferenceTest.java | 84 +++++++++++++++++++ 6 files changed, 253 insertions(+), 5 deletions(-) create mode 100644 src/com/android/settings/widget/MutableGearPreference.java create mode 100644 tests/unit/src/com/android/settings/widget/GearPreferenceTest.java create mode 100644 tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java index 2d23f1f618e..e0f20cdb583 100644 --- a/src/com/android/settings/network/SubscriptionsPreferenceController.java +++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.graphics.drawable.Drawable; import android.net.wifi.WifiManager; +import android.os.UserManager; import android.provider.Settings; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -55,7 +56,7 @@ import com.android.settings.network.telephony.MobileNetworkActivity; import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.network.telephony.SignalStrengthListener; import com.android.settings.network.telephony.TelephonyDisplayInfoListener; -import com.android.settings.widget.GearPreference; +import com.android.settings.widget.MutableGearPreference; import com.android.settings.wifi.WifiPickerTrackerHelper; import com.android.settingslib.SignalIcon.MobileIconGroup; import com.android.settingslib.core.AbstractPreferenceController; @@ -115,7 +116,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl // Map of subscription id to Preference private Map mSubscriptionPreferences; private int mStartOrder; - private GearPreference mSubsGearPref; + private MutableGearPreference mSubsGearPref; private Config mConfig = null; private SubsPrefCtrlInjector mSubsPrefCtrlInjector; private TelephonyDisplayInfo mTelephonyDisplayInfo = @@ -238,15 +239,20 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl } if (mSubsGearPref == null) { mPreferenceGroup.removeAll(); - mSubsGearPref = new GearPreference(mContext, null); + mSubsGearPref = new MutableGearPreference(mContext, null); mSubsGearPref.setOnPreferenceClickListener(preference -> { connectCarrierNetwork(); return true; }); + mSubsGearPref.setOnGearClickListener(p -> startMobileNetworkActivity(mContext, subInfo.getSubscriptionId())); } + if (!(mContext.getSystemService(UserManager.class)).isAdminUser()) { + mSubsGearPref.setGearEnabled(false); + } + mSubsGearPref.setTitle(SubscriptionUtil.getUniqueSubscriptionDisplayName( subInfo, mContext)); mSubsGearPref.setOrder(mStartOrder); diff --git a/src/com/android/settings/widget/GearPreference.java b/src/com/android/settings/widget/GearPreference.java index 0a301006698..82bc1f0c203 100644 --- a/src/com/android/settings/widget/GearPreference.java +++ b/src/com/android/settings/widget/GearPreference.java @@ -29,7 +29,8 @@ import com.android.settingslib.RestrictedPreference; * A preference with a Gear on the side */ public class GearPreference extends RestrictedPreference implements View.OnClickListener { - + // Default true for gear available even if the preference itself is disabled. + protected boolean mGearState = true; private OnGearClickListener mOnGearClickListener; public GearPreference(Context context, AttributeSet attrs) { @@ -41,6 +42,16 @@ public class GearPreference extends RestrictedPreference implements View.OnClick notifyChanged(); } + /** Sets state of gear button. */ + public void setGearEnabled(boolean enabled) { + mGearState = enabled; + } + + /** Gets state of gear button. */ + public boolean isGearEnabled() { + return mGearState; + } + @Override protected int getSecondTargetResId() { return R.layout.preference_widget_gear; @@ -62,7 +73,8 @@ public class GearPreference extends RestrictedPreference implements View.OnClick gear.setVisibility(View.GONE); gear.setOnClickListener(null); } - gear.setEnabled(true); // Make gear available even if the preference itself is disabled. + // Make gear available even if the preference itself is disabled. + gear.setEnabled(mGearState); } @Override diff --git a/src/com/android/settings/widget/MutableGearPreference.java b/src/com/android/settings/widget/MutableGearPreference.java new file mode 100644 index 00000000000..b0804ebc2db --- /dev/null +++ b/src/com/android/settings/widget/MutableGearPreference.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 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.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ImageView; + +import androidx.preference.PreferenceViewHolder; + +import com.android.settings.R; +import com.android.settingslib.utils.ColorUtil; + +/** A preference with a Gear on the side and mutable Gear color. */ +public class MutableGearPreference extends GearPreference { + private static final int VALUE_ENABLED_ALPHA = 255; + + private ImageView mGear; + private Context mContext; + private int mDisabledAlphaValue; + + public MutableGearPreference(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + mDisabledAlphaValue = (int) (ColorUtil.getDisabledAlpha(context) * VALUE_ENABLED_ALPHA); + } + + @Override + public void setGearEnabled(boolean enabled) { + if (mGear != null) { + mGear.setEnabled(enabled); + mGear.setImageAlpha(enabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue); + } + mGearState = enabled; + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + mGear = (ImageView) holder.findViewById(R.id.settings_button); + setGearEnabled(mGearState); + } +} diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java index 0ef44eef270..fc18ce71268 100644 --- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java @@ -40,6 +40,7 @@ import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.os.Looper; +import android.os.UserManager; import android.provider.Settings; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -81,6 +82,8 @@ import java.util.List; public class SubscriptionsPreferenceControllerTest { private static final String KEY = "preference_group"; + @Mock + private UserManager mUserManager; @Mock private SubscriptionManager mSubscriptionManager; @Mock @@ -121,10 +124,12 @@ public class SubscriptionsPreferenceControllerTest { when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork); when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork)) .thenReturn(mNetworkCapabilities); + when(mUserManager.isAdminUser()).thenReturn(true); when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry); mPreferenceManager = new PreferenceManager(mContext); diff --git a/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java b/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java new file mode 100644 index 00000000000..a47eade61c3 --- /dev/null +++ b/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2021 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.widget; + +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.view.LayoutInflater; +import android.view.View; + +import androidx.preference.PreferenceViewHolder; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.testutils.ResourcesUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unittest for GearPreference */ +@RunWith(AndroidJUnit4.class) +public class GearPreferenceTest { + @Mock + private GearPreference.OnGearClickListener mOnGearClickListener; + + private Context mContext = ApplicationProvider.getApplicationContext(); + private GearPreference mGearPreference; + private PreferenceViewHolder mViewHolder; + private View mGearView; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mGearPreference = + new GearPreference(mContext, null); + int layoutId = ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear"); + PreferenceViewHolder holder = + PreferenceViewHolder.createInstanceForTests( + LayoutInflater.from(ApplicationProvider.getApplicationContext()) + .inflate(layoutId, null)); + mViewHolder = spy(holder); + mGearView = new View(mContext, null); + int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button"); + when(mViewHolder.findViewById(gearId)).thenReturn(mGearView); + } + + @Test + public void onBindViewHolder_gearIsVisible() { + mGearPreference.setOnGearClickListener(mOnGearClickListener); + + mGearPreference.onBindViewHolder(mViewHolder); + + assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void onBindViewHolder_gearIsGone() { + mGearPreference.setOnGearClickListener(null); + + mGearPreference.onBindViewHolder(mViewHolder); + + assertThat(mGearView.getVisibility()).isEqualTo(View.GONE); + } +} diff --git a/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java b/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java new file mode 100644 index 00000000000..44b1d380508 --- /dev/null +++ b/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2021 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.widget; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.widget.ImageView; + +import androidx.preference.PreferenceViewHolder; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.testutils.ResourcesUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unittest for MutableGearPreference */ +@RunWith(AndroidJUnit4.class) +public class MutableGearPreferenceTest { + @Mock + private MutableGearPreference.OnGearClickListener mOnGearClickListener; + + private Context mContext = ApplicationProvider.getApplicationContext(); + private MutableGearPreference mMutableGearPreference; + private PreferenceViewHolder mViewHolder; + private ImageView mGearView; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mMutableGearPreference = + new MutableGearPreference(mContext, null); + int layoutId = + ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear"); + PreferenceViewHolder holder = + PreferenceViewHolder.createInstanceForTests( + LayoutInflater.from(ApplicationProvider.getApplicationContext()) + .inflate(layoutId, null)); + mViewHolder = spy(holder); + mGearView = spy(new ImageView(mContext, null)); + int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button"); + when(mViewHolder.findViewById(gearId)).thenReturn(mGearView); + } + + @Test + public void onBindViewHolder_gearChangeAlpha() { + mMutableGearPreference.setGearEnabled(false); + mMutableGearPreference.setOnGearClickListener(mOnGearClickListener); + + mMutableGearPreference.onBindViewHolder(mViewHolder); + + verify(mGearView).setImageAlpha(anyInt()); + } + + private static int getDisabledAlphaValue(Context context) { + TypedValue value = new TypedValue(); + context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true); + return (int) (value.getFloat() * 255); + } +} From 4d7da4a425dbedec151f9e902962a037287ce5e6 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Tue, 8 Jun 2021 18:55:49 +0800 Subject: [PATCH 02/14] Remove FLAG_ACTIVITY_NEW_TASk when there is transition Making activities launch in a separate task breaks the page transition. Reviewed the history of the addition of these flags, they seem stale and are no longer needed, so remove these when the transition is applied. Bug: 189412031 Test: Tap on any badged entry and see it being launched in the same task. Change-Id: I60b2ec0b2772cd3bdc8c4ebbc83cedd2a603492a --- src/com/android/settings/core/SubSettingLauncher.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java index 893d592fe78..0a6966fe17f 100644 --- a/src/com/android/settings/core/SubSettingLauncher.java +++ b/src/com/android/settings/core/SubSettingLauncher.java @@ -28,6 +28,7 @@ import androidx.fragment.app.Fragment; import com.android.settings.SettingsActivity; import com.android.settings.SubSettings; +import com.android.settings.Utils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.transition.SettingsTransitionHelper.TransitionType; @@ -181,8 +182,10 @@ public class SubSettingLauncher { @VisibleForTesting void launchAsUser(Intent intent, UserHandle userHandle) { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + if (!Utils.isPageTransitionEnabled(mContext)) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + } mContext.startActivityAsUser(intent, userHandle); } From a0a7ff6d76b0ddf3a9d0a16d8cc250ffc6969402 Mon Sep 17 00:00:00 2001 From: Edgar Wang Date: Tue, 8 Jun 2021 20:13:48 +0800 Subject: [PATCH 03/14] Moving progressBarHorizontalStyle to SettingsLib Bug: 190467533 Test: rebuild & manual Change-Id: I5f7f493b7c100c06ff5328706906bf33bae34e56 --- res/drawable/progress_horizontal.xml | 38 ---------------------------- res/values/styles.xml | 6 ----- res/values/themes.xml | 1 - 3 files changed, 45 deletions(-) delete mode 100644 res/drawable/progress_horizontal.xml diff --git a/res/drawable/progress_horizontal.xml b/res/drawable/progress_horizontal.xml deleted file mode 100644 index f2a4cc4ce49..00000000000 --- a/res/drawable/progress_horizontal.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/res/values/styles.xml b/res/values/styles.xml index 6021a7c226e..ae77cc23a18 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -404,12 +404,6 @@ @drawable/ring_progress - - diff --git a/res/values/themes.xml b/res/values/themes.xml index df7d43369e6..4c5cdb7291f 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -32,7 +32,6 @@ @drawable/ic_arrow_back @android:color/transparent @style/PickerDialogTheme.Settings - @style/HorizontalProgressBarStyle @style/FingerprintLayoutTheme @style/FaceLayoutTheme From 4f3ac2fcbd733fcf96633ac610e403259c94666b Mon Sep 17 00:00:00 2001 From: tom hsu Date: Mon, 7 Jun 2021 16:47:39 +0800 Subject: [PATCH 04/14] [Settings] Resolves unsynced infomation between status bar and settings When activity go to background, the UI message shall be saved, and When activity is back to foreground, the UI shows previous state first. The situation make unsynced info between status bar and settings's page. Bug: 187091965 Test: Maunal Test Test: atest passed Change-Id: I7db2876e91c00126ebfa9dfa5b87d04c1f717e72 --- .../network/SubscriptionsPreferenceController.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java index 2d23f1f618e..3e568e9da26 100644 --- a/src/com/android/settings/network/SubscriptionsPreferenceController.java +++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java @@ -38,6 +38,7 @@ import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.text.Html; import android.util.ArraySet; +import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.collection.ArrayMap; @@ -196,6 +197,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl mSignalStrengthListener.pause(); mTelephonyDisplayInfoListener.pause(); unRegisterReceiver(); + resetProviderPreferenceSummary(); } @Override @@ -275,6 +277,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl String result = mSubsPrefCtrlInjector.getNetworkType( mContext, mConfig, mTelephonyDisplayInfo, subId, isActiveCarrierNetwork); if (mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext) || isActiveCarrierNetwork) { + Log.i(TAG, "Active cellular network or active carrier network."); result = mContext.getString(R.string.preference_summary_default_combination, mContext.getString(R.string.mobile_data_connection_active), result); } else if (!isDataInService) { @@ -316,6 +319,13 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl return icon; } + private void resetProviderPreferenceSummary() { + if (mSubsGearPref == null) { + return; + } + mSubsGearPref.setSummary(""); + } + private void updateForBase() { final Map existingPrefs = mSubscriptionPreferences; mSubscriptionPreferences = new ArrayMap<>(); From 4ef143851265e9e8d20318307b552f66679a1b9e Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Mon, 7 Jun 2021 14:38:45 +0100 Subject: [PATCH 05/14] RequestManageCredentials landscape mode * Split screen into two halves, where the left side includes the title and the right side includes the recycler view, floating action button and action buttons. * https://screenshot.googleplex.com/6Co6kn2DyXZRGNZ * https://screenshot.googleplex.com/6uwHAGuRHjNcStN Bug: 189193577 Test: manual testing via TestDPC RequestManageCredentialsTest Change-Id: I9c82a7471c885658aacb40b22166ec801e2833ca --- .../request_manage_credentials.xml | 139 ++++++++++++++++++ res/values/styles.xml | 7 + .../security/RequestManageCredentials.java | 36 ++++- 3 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 res/layout-land/request_manage_credentials.xml diff --git a/res/layout-land/request_manage_credentials.xml b/res/layout-land/request_manage_credentials.xml new file mode 100644 index 00000000000..bf00098e723 --- /dev/null +++ b/res/layout-land/request_manage_credentials.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +