From 77b62b24c6d386f7913bfe16e1ab121404c3b50a Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 19 Jun 2018 16:52:07 -0700 Subject: [PATCH 01/16] Update PBAP info for all pairing dialogs. DO NOT MERGE This is a bug from ag/4210612, in which it only update PBAP info for USER_ENTRY_DIALOG. So in other kind of dialogs it never upload correct PBAP info to bluetooth backend. This CL fix it by updating PBAP for all dialogs. Change-Id: Ia39eee1acaece555e8e5a305ec2c803294d7efbd Bug: 109842273 Bug: 72872376 Test: RunSettingsRoboTests (cherry picked from commit 7015e20a554fd7f8f7ded7359a5ecc13a82a0464) --- .../bluetooth/BluetoothPairingController.java | 22 ++++--- .../BluetoothPairingControllerTest.java | 66 +++++++++++++++++++ 2 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java index 5120cc0ff9b..4b9ffdad4eb 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingController.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java @@ -23,12 +23,16 @@ import android.text.Editable; import android.util.Log; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; + import com.android.settings.R; import com.android.settings.bluetooth.BluetoothPairingDialogFragment.BluetoothPairingDialogListener; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; + import java.util.Locale; +import android.support.annotation.VisibleForTesting; + /** * A controller used by {@link BluetoothPairingDialog} to manage connection state while we try to * pair with a bluetooth device. It includes methods that allow the @@ -50,8 +54,10 @@ public class BluetoothPairingController implements OnCheckedChangeListener, // Bluetooth dependencies for the connection we are trying to establish private LocalBluetoothManager mBluetoothManager; - private BluetoothDevice mDevice; - private int mType; + @VisibleForTesting + BluetoothDevice mDevice; + @VisibleForTesting + int mType; private String mUserInput; private String mPasskeyFormatted; private int mPasskey; @@ -82,7 +88,6 @@ public class BluetoothPairingController implements OnCheckedChangeListener, mDeviceName = mBluetoothManager.getCachedDeviceManager().getName(mDevice); mPbapClientProfile = mBluetoothManager.getProfileManager().getPbapClientProfile(); mPasskeyFormatted = formatKey(mPasskey); - } @Override @@ -96,12 +101,13 @@ public class BluetoothPairingController implements OnCheckedChangeListener, @Override public void onDialogPositiveClick(BluetoothPairingDialogFragment dialog) { + if (mPbapAllowed) { + mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); + } else { + mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); + } + if (getDialogType() == USER_ENTRY_DIALOG) { - if (mPbapAllowed) { - mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); - } else { - mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); - } onPair(mUserInput); } else { onPair(null); diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java new file mode 100644 index 00000000000..b28a8b2b825 --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingControllerTest.java @@ -0,0 +1,66 @@ +/* + * 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.bluetooth; + +import static android.bluetooth.BluetoothDevice.PAIRING_VARIANT_CONSENT; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.bluetooth.BluetoothDevice; +import android.content.Context; +import android.content.Intent; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; +import com.android.settings.testutils.shadow.ShadowBluetoothPan; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = {ShadowBluetoothPan.class, ShadowBluetoothAdapter.class}) +public class BluetoothPairingControllerTest { + @Mock + private BluetoothDevice mBluetoothDevice; + private Context mContext; + private BluetoothPairingController mBluetoothPairingController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = RuntimeEnvironment.application; + final Intent intent = new Intent(); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + mBluetoothPairingController = spy(new BluetoothPairingController(intent, mContext)); + } + + @Test + public void onDialogPositiveClick_confirmationDialog_setPBAP() { + mBluetoothPairingController.mType = PAIRING_VARIANT_CONSENT; + mBluetoothPairingController.onCheckedChanged(null, true); + + mBluetoothPairingController.onDialogPositiveClick(null); + + verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); + } +} From bad5898fb66f9163368614db88d1f3639e0390b7 Mon Sep 17 00:00:00 2001 From: Chienyuan Date: Wed, 5 Sep 2018 11:10:01 +0800 Subject: [PATCH 02/16] Don't update state after stop bluetooth tethering After using ConnectivityManager.stopTethering(), TetheringSettings may update state before PanService set mTetherOn to false. This makes the toggle button checked again and user need click it twice to disable it. Bug: 111578971 Test: on/off bluetooth tethering from settings UI Change-Id: I6873d762d2a290080d844b7a44e54f4bd532347e --- src/com/android/settings/TetherSettings.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 02f9cc5cc7d..d32e387ae46 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -423,9 +423,6 @@ public class TetherSettings extends RestrictedSettingsFragment startTethering(TETHERING_BLUETOOTH); } else { mCm.stopTethering(TETHERING_BLUETOOTH); - // No ACTION_TETHER_STATE_CHANGED is fired or bluetooth unless a device is - // connected. Need to update state manually. - updateState(); } } From ef814b81fc8eefdeb8f3fb37ad1f220b9a4330d3 Mon Sep 17 00:00:00 2001 From: Antony Sargent Date: Tue, 4 Sep 2018 14:41:21 -0700 Subject: [PATCH 03/16] Fix Battery Usage graph layout for small screens In PowerGaugePreference, if there isn't an icon to show, we were just adding an empty one, which causes space to be reserved and isn't what we want on small screens. Bug: 111318404 Test: visual (set display size to Larger or Largest, and visit Battery page in settings; the "Last full charge" and Screen usage since full charge" items at the bottom should not be indented) Change-Id: I60d39836ab7d50234022a377ff6d97dde8d4c7db --- src/com/android/settings/fuelgauge/PowerGaugePreference.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java index a2ceb67cab7..7c217744945 100644 --- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java +++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java @@ -58,7 +58,9 @@ public class PowerGaugePreference extends AppPreference { private PowerGaugePreference(Context context, AttributeSet attrs, Drawable icon, CharSequence contentDescription, BatteryEntry info) { super(context, attrs); - setIcon(icon != null ? icon : new ColorDrawable(0)); + if (icon != null) { + setIcon(icon); + } setWidgetLayoutResource(R.layout.preference_widget_summary); mInfo = info; mContentDescription = contentDescription; From 8c71a24e435eb09347b218008f4c7f7dda65bcc8 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Wed, 5 Sep 2018 20:35:37 +0800 Subject: [PATCH 04/16] Switch to GridLayoutManager to support two-column layout In order to display both half-width card and full-width card, we use GridLayoutManager and SpanSizeLookup to achieve this purpose. Bug: 111822407 Test: manual Change-Id: I225fb0b5f731e3faf2bca9858395c40d318acf2f --- .../settings/homepage/HomepageAdapter.java | 21 +++++++++++++++++-- .../homepage/PersonalSettingsFragment.java | 9 +++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/homepage/HomepageAdapter.java b/src/com/android/settings/homepage/HomepageAdapter.java index 9ff52603dab..bd376012223 100644 --- a/src/com/android/settings/homepage/HomepageAdapter.java +++ b/src/com/android/settings/homepage/HomepageAdapter.java @@ -21,6 +21,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; @@ -28,14 +29,16 @@ import java.util.List; public class HomepageAdapter extends RecyclerView.Adapter implements HomepageCardUpdateListener { + static final int SPAN_COUNT = 2; private static final String TAG = "HomepageAdapter"; + private static final int HALF_WIDTH = 1; + private static final int FULL_WIDTH = 2; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private List mHomepageCards; - private RecyclerView mRecyclerView; public HomepageAdapter(Context context, HomepageManager manager) { mContext = context; @@ -81,7 +84,21 @@ public class HomepageAdapter extends RecyclerView.Adapter Date: Thu, 6 Sep 2018 12:21:30 -0700 Subject: [PATCH 05/16] Move safety & regulatory manual closer to legal settings Bug: 113788849 Test: visual Change-Id: Ie9a706bad9a4c65ff06c2350171ad55f46dd8386 --- res/xml/my_device_info.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml index 957ba81c57e..535f61afa5d 100644 --- a/res/xml/my_device_info.xml +++ b/res/xml/my_device_info.xml @@ -72,10 +72,18 @@ + + + + + - - - - - Date: Thu, 6 Sep 2018 12:21:30 -0700 Subject: [PATCH 06/16] Move safety & regulatory manual closer to legal settings Bug: 113788849 Test: visual Change-Id: Ie9a706bad9a4c65ff06c2350171ad55f46dd8386 Merged-In: Ie9a706bad9a4c65ff06c2350171ad55f46dd8386 --- res/xml/my_device_info.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml index 3dac8b879f2..3d499ab4600 100644 --- a/res/xml/my_device_info.xml +++ b/res/xml/my_device_info.xml @@ -71,10 +71,18 @@ + + + + + - - - - - - \ No newline at end of file + From ff171eff8ea2e65e3f400cf5cb6ce025402381ce Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 19 Jun 2018 16:52:07 -0700 Subject: [PATCH 07/16] Update PBAP info for all pairing dialogs. DO NOT MERGE This is a bug from ag/4210612, in which it only update PBAP info for USER_ENTRY_DIALOG. So in other kind of dialogs it never upload correct PBAP info to bluetooth backend. This CL fix it by updating PBAP for all dialogs. Change-Id: Ia39eee1acaece555e8e5a305ec2c803294d7efbd Merged-In: Ia39eee1acaece555e8e5a305ec2c803294d7efbd Bug: 109842273 Bug: 72872376 Test: RunSettingsRoboTests (cherry picked from commit 7015e20a554fd7f8f7ded7359a5ecc13a82a0464) --- .../bluetooth/BluetoothPairingController.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java index d06cb7e0376..96837e45f81 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingController.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java @@ -23,12 +23,16 @@ import android.text.Editable; import android.util.Log; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; + import com.android.settings.R; import com.android.settings.bluetooth.BluetoothPairingDialogFragment.BluetoothPairingDialogListener; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; + import java.util.Locale; +import android.support.annotation.VisibleForTesting; + /** * A controller used by {@link BluetoothPairingDialog} to manage connection state while we try to * pair with a bluetooth device. It includes methods that allow the @@ -50,8 +54,10 @@ public class BluetoothPairingController implements OnCheckedChangeListener, // Bluetooth dependencies for the connection we are trying to establish private LocalBluetoothManager mBluetoothManager; - private BluetoothDevice mDevice; - private int mType; + @VisibleForTesting + BluetoothDevice mDevice; + @VisibleForTesting + int mType; private String mUserInput; private String mPasskeyFormatted; private int mPasskey; @@ -82,7 +88,6 @@ public class BluetoothPairingController implements OnCheckedChangeListener, mDeviceName = mBluetoothManager.getCachedDeviceManager().getName(mDevice); mPbapClientProfile = mBluetoothManager.getProfileManager().getPbapClientProfile(); mPasskeyFormatted = formatKey(mPasskey); - } @Override @@ -96,12 +101,13 @@ public class BluetoothPairingController implements OnCheckedChangeListener, @Override public void onDialogPositiveClick(BluetoothPairingDialogFragment dialog) { + if (mPbapAllowed) { + mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); + } else { + mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); + } + if (getDialogType() == USER_ENTRY_DIALOG) { - if (mPbapAllowed) { - mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); - } else { - mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); - } onPair(mUserInput); } else { onPair(null); From 21526c1f801bb6fa41de503cc4e09523ada41475 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 6 Sep 2018 15:44:26 -0700 Subject: [PATCH 08/16] Launch the new TopLevelSettings for all settings tab. The new TopLevelSettings page uses a standard DashboardFragment to host all top level settings. It's easier to maintain than DashboardSummary. It does not support conditional cards or suggestion cards. We will use PersonalSettingsFragment to host these as contextual cards going forward. Bug: 110405144 Test: visual Change-Id: I2ab2d3556e870e86ebc18f9876336c4a3a361897 --- src/com/android/settings/SettingsActivity.java | 10 ++++++++-- src/com/android/settings/SettingsHomepageActivity.java | 6 +++--- .../settings/homepage/PersonalSettingsFragment.java | 2 +- .../src/com/android/settings/SettingsActivityTest.java | 9 ++++++--- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 4ca1c2cb688..cde2aca820c 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -62,6 +62,7 @@ import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.gateway.SettingsGateway; import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.dashboard.DashboardSummary; +import com.android.settings.homepage.TopLevelSettings; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.DeviceIndexFeatureProvider; import com.android.settings.wfd.WifiDisplaySettings; @@ -403,8 +404,13 @@ public class SettingsActivity extends SettingsBaseActivity // Show search icon as up affordance if we are displaying the main Dashboard mInitialTitleResId = R.string.dashboard_title; - switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false, - mInitialTitleResId, mInitialTitle, false); + if (SettingsHomepageActivity.isDynamicHomepageEnabled(this)) { + switchToFragment(TopLevelSettings.class.getName(), null /* args */, false, false, + mInitialTitleResId, mInitialTitle, false); + } else { + switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false, + mInitialTitleResId, mInitialTitle, false); + } } } diff --git a/src/com/android/settings/SettingsHomepageActivity.java b/src/com/android/settings/SettingsHomepageActivity.java index de25cf4e27a..77155e00000 100644 --- a/src/com/android/settings/SettingsHomepageActivity.java +++ b/src/com/android/settings/SettingsHomepageActivity.java @@ -29,6 +29,7 @@ import com.android.settings.core.FeatureFlags; import com.android.settings.core.SettingsBaseActivity; import com.android.settings.dashboard.DashboardSummary; import com.android.settings.homepage.PersonalSettingsFragment; +import com.android.settings.homepage.TopLevelSettings; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.SearchFeatureProvider; @@ -58,8 +59,7 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { FeatureFactory.getFactory(this).getSearchFeatureProvider() .initSearchToolbar(this, searchButton); - final BottomNavigationView navigation = (BottomNavigationView) findViewById( - R.id.bottom_nav); + final BottomNavigationView navigation = findViewById(R.id.bottom_nav); navigation.setOnNavigationItemSelectedListener(item -> { switch (item.getItemId()) { case R.id.homepage_personal_settings: @@ -68,7 +68,7 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { return true; case R.id.homepage_all_settings: - switchFragment(DashboardSummary.class.getName(), ALL_SETTINGS_TAG, + switchFragment(TopLevelSettings.class.getName(), ALL_SETTINGS_TAG, PERSONAL_SETTINGS_TAG); return true; } diff --git a/src/com/android/settings/homepage/PersonalSettingsFragment.java b/src/com/android/settings/homepage/PersonalSettingsFragment.java index b515e294071..1894e5e3696 100644 --- a/src/com/android/settings/homepage/PersonalSettingsFragment.java +++ b/src/com/android/settings/homepage/PersonalSettingsFragment.java @@ -54,7 +54,7 @@ public class PersonalSettingsFragment extends InstrumentedFragment { Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.settings_homepage, container, false); - mCardsContainer = (RecyclerView) rootView.findViewById(R.id.card_container); + mCardsContainer = rootView.findViewById(R.id.card_container); mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT, LinearLayoutManager.VERTICAL, false /* reverseLayout */); mCardsContainer.setLayoutManager(mLayoutManager); diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java index 723978f9bb1..409512eb140 100644 --- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java +++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java @@ -73,10 +73,11 @@ public class SettingsActivityTest { Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0); final Intent intent = new Intent(mContext, Settings.class); final SettingsActivity activity = - Robolectric.buildActivity(SettingsActivity.class, intent).create(Bundle.EMPTY).get(); + Robolectric.buildActivity(SettingsActivity.class, intent).create( + Bundle.EMPTY).get(); assertThat(activity.findViewById(R.id.search_bar).getVisibility()) - .isEqualTo(View.INVISIBLE); + .isEqualTo(View.INVISIBLE); } @Test @@ -84,7 +85,8 @@ public class SettingsActivityTest { Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1); final Intent intent = new Intent(mContext, Settings.class); final SettingsActivity activity = - Robolectric.buildActivity(SettingsActivity.class, intent).create(Bundle.EMPTY).get(); + Robolectric.buildActivity(SettingsActivity.class, intent).create( + Bundle.EMPTY).get(); assertThat(activity.findViewById(R.id.search_bar).getVisibility()).isEqualTo(View.VISIBLE); } @@ -92,6 +94,7 @@ public class SettingsActivityTest { @Test public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() { when(mActivity.getSupportFragmentManager()).thenReturn(mFragmentManager); + doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver(); when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class)); doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader(); From a7463814014691acfd554b7098f9801fd2148915 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 6 Sep 2018 17:45:50 -0700 Subject: [PATCH 09/16] Rename a bunch of stuff. For homepage cards, rename Homepage* to ContextualCard*. Change-Id: I95740f15a1789683fa6c61f03ecf9bc47c367146 Fixes: 113966426 Test: robotests --- .../settings/homepage/CardContentLoader.java | 8 +-- ...{HomepageCard.java => ContextualCard.java} | 16 ++--- ...ler.java => ContextualCardController.java} | 16 ++--- ...le.java => ContextualCardLookupTable.java} | 40 ++++++------ ...anager.java => ContextualCardManager.java} | 62 +++++++++---------- ...derer.java => ContextualCardRenderer.java} | 10 +-- ...java => ContextualCardUpdateListener.java} | 12 ++-- ...apter.java => ContextualCardsAdapter.java} | 36 +++++------ .../homepage/ControllerRendererPool.java | 50 +++++++-------- .../homepage/PersonalSettingsFragment.java | 18 +++--- ...=> ConditionContextualCardController.java} | 53 ++++++++-------- ...a => ConditionContextualCardRenderer.java} | 20 +++--- ...rd.java => ConditionalContextualCard.java} | 16 ++--- ...onditionContextualCardControllerTest.java} | 12 ++-- ... ConditionContextualCardRendererTest.java} | 29 +++++---- 15 files changed, 199 insertions(+), 199 deletions(-) rename src/com/android/settings/homepage/{HomepageCard.java => ContextualCard.java} (95%) rename src/com/android/settings/homepage/{HomepageCardController.java => ContextualCardController.java} (68%) rename src/com/android/settings/homepage/{HomepageCardLookupTable.java => ContextualCardLookupTable.java} (50%) rename src/com/android/settings/homepage/{HomepageManager.java => ContextualCardManager.java} (56%) rename src/com/android/settings/homepage/{HomepageCardRenderer.java => ContextualCardRenderer.java} (76%) rename src/com/android/settings/homepage/{HomepageCardUpdateListener.java => ContextualCardUpdateListener.java} (59%) rename src/com/android/settings/homepage/{HomepageAdapter.java => ContextualCardsAdapter.java} (72%) rename src/com/android/settings/homepage/conditional/{ConditionHomepageCardController.java => ConditionContextualCardController.java} (55%) rename src/com/android/settings/homepage/conditional/{ConditionHomepageCardRenderer.java => ConditionContextualCardRenderer.java} (89%) rename src/com/android/settings/homepage/conditional/{ConditionCard.java => ConditionalContextualCard.java} (81%) rename tests/robotests/src/com/android/settings/homepage/conditional/{ConditionHomepageCardControllerTest.java => ConditionContextualCardControllerTest.java} (91%) rename tests/robotests/src/com/android/settings/homepage/conditional/{ConditionHomepageCardRendererTest.java => ConditionContextualCardRendererTest.java} (79%) diff --git a/src/com/android/settings/homepage/CardContentLoader.java b/src/com/android/settings/homepage/CardContentLoader.java index 4e1e33ef891..47ba59afe8e 100644 --- a/src/com/android/settings/homepage/CardContentLoader.java +++ b/src/com/android/settings/homepage/CardContentLoader.java @@ -32,7 +32,7 @@ public class CardContentLoader { private CardContentLoaderListener mListener; public interface CardContentLoaderListener { - void onFinishCardLoading(List homepageCards); + void onFinishCardLoading(List contextualCards); } public CardContentLoader() { @@ -42,20 +42,20 @@ public class CardContentLoader { mListener = listener; } - private static class CardLoader extends AsyncLoaderCompat> { + private static class CardLoader extends AsyncLoaderCompat> { public CardLoader(Context context) { super(context); } @Override - protected void onDiscardResult(List result) { + protected void onDiscardResult(List result) { } @Nullable @Override - public List loadInBackground() { + public List loadInBackground() { return null; } } diff --git a/src/com/android/settings/homepage/HomepageCard.java b/src/com/android/settings/homepage/ContextualCard.java similarity index 95% rename from src/com/android/settings/homepage/HomepageCard.java rename to src/com/android/settings/homepage/ContextualCard.java index 1469ff1896d..f5083d80e6c 100644 --- a/src/com/android/settings/homepage/HomepageCard.java +++ b/src/com/android/settings/homepage/ContextualCard.java @@ -25,12 +25,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Data class representing a {@link HomepageCard}. + * Data class representing a {@link ContextualCard}. */ -public class HomepageCard { +public class ContextualCard { /** - * Flags indicating the type of the HomepageCard. + * Flags indicating the type of the ContextualCard. */ @IntDef({CardType.INVALID, CardType.SLICE, CardType.SUGGESTION, CardType.CONDITIONAL}) @Retention(RetentionPolicy.SOURCE) @@ -137,7 +137,7 @@ public class HomepageCard { return mIsHalfWidth; } - public HomepageCard(Builder builder) { + public ContextualCard(Builder builder) { mName = builder.mName; mCardType = builder.mCardType; mRankingScore = builder.mRankingScore; @@ -171,10 +171,10 @@ public class HomepageCard { if (this == obj) { return true; } - if (!(obj instanceof HomepageCard)) { + if (!(obj instanceof ContextualCard)) { return false; } - final HomepageCard that = (HomepageCard) obj; + final ContextualCard that = (ContextualCard) obj; return TextUtils.equals(mName, that.mName); } @@ -289,8 +289,8 @@ public class HomepageCard { return this; } - public HomepageCard build() { - return new HomepageCard(this); + public ContextualCard build() { + return new ContextualCard(this); } } } diff --git a/src/com/android/settings/homepage/HomepageCardController.java b/src/com/android/settings/homepage/ContextualCardController.java similarity index 68% rename from src/com/android/settings/homepage/HomepageCardController.java rename to src/com/android/settings/homepage/ContextualCardController.java index a7d89afc504..921d72bda8a 100644 --- a/src/com/android/settings/homepage/HomepageCardController.java +++ b/src/com/android/settings/homepage/ContextualCardController.java @@ -19,22 +19,22 @@ package com.android.settings.homepage; import java.util.List; /** - * Data controller for {@link HomepageCard}. + * Data controller for {@link ContextualCard}. */ -public interface HomepageCardController { +public interface ContextualCardController { - @HomepageCard.CardType + @ContextualCard.CardType int getCardType(); /** - * When data is updated or changed, the new data should be passed to HomepageManager for list + * When data is updated or changed, the new data should be passed to ContextualCardManager for list * updating. */ - void onDataUpdated(List cardList); + void onDataUpdated(List cardList); - void onPrimaryClick(HomepageCard card); + void onPrimaryClick(ContextualCard card); - void onActionClick(HomepageCard card); + void onActionClick(ContextualCard card); - void setHomepageCardUpdateListener(HomepageCardUpdateListener listener); + void setCardUpdateListener(ContextualCardUpdateListener listener); } diff --git a/src/com/android/settings/homepage/HomepageCardLookupTable.java b/src/com/android/settings/homepage/ContextualCardLookupTable.java similarity index 50% rename from src/com/android/settings/homepage/HomepageCardLookupTable.java rename to src/com/android/settings/homepage/ContextualCardLookupTable.java index 8d8e52b183e..e70b700fea2 100644 --- a/src/com/android/settings/homepage/HomepageCardLookupTable.java +++ b/src/com/android/settings/homepage/ContextualCardLookupTable.java @@ -16,43 +16,45 @@ package com.android.settings.homepage; -import com.android.settings.homepage.HomepageCard.CardType; -import com.android.settings.homepage.conditional.ConditionHomepageCardController; -import com.android.settings.homepage.conditional.ConditionHomepageCardRenderer; +import com.android.settings.homepage.ContextualCard.CardType; +import com.android.settings.homepage.conditional.ConditionContextualCardController; +import com.android.settings.homepage.conditional.ConditionContextualCardRenderer; import java.util.Set; import java.util.TreeSet; -public class HomepageCardLookupTable { +public class ContextualCardLookupTable { - static class HomepageMapping implements Comparable { + static class ControllerRendererMapping implements Comparable { @CardType private final int mCardType; - private final Class mControllerClass; - private final Class mRendererClass; + private final Class mControllerClass; + private final Class mRendererClass; - private HomepageMapping(@CardType int cardType, - Class controllerClass, - Class rendererClass) { + private ControllerRendererMapping(@CardType int cardType, + Class controllerClass, + Class rendererClass) { mCardType = cardType; mControllerClass = controllerClass; mRendererClass = rendererClass; } @Override - public int compareTo(HomepageMapping other) { + public int compareTo(ControllerRendererMapping other) { return Integer.compare(this.mCardType, other.mCardType); } } - private static final Set LOOKUP_TABLE = new TreeSet() {{ - add(new HomepageMapping(CardType.CONDITIONAL, ConditionHomepageCardController.class, - ConditionHomepageCardRenderer.class)); - }}; + private static final Set LOOKUP_TABLE = + new TreeSet() {{ + add(new ControllerRendererMapping(CardType.CONDITIONAL, + ConditionContextualCardController.class, + ConditionContextualCardRenderer.class)); + }}; - public static Class getCardControllerClass( + public static Class getCardControllerClass( @CardType int cardType) { - for (HomepageMapping mapping : LOOKUP_TABLE) { + for (ControllerRendererMapping mapping : LOOKUP_TABLE) { if (mapping.mCardType == cardType) { return mapping.mControllerClass; } @@ -61,9 +63,9 @@ public class HomepageCardLookupTable { } //TODO(b/112578070): Implement multi renderer cases. - public static Class getCardRendererClasses( + public static Class getCardRendererClasses( @CardType int cardType) { - for (HomepageMapping mapping : LOOKUP_TABLE) { + for (ControllerRendererMapping mapping : LOOKUP_TABLE) { if (mapping.mCardType == cardType) { return mapping.mRendererClass; } diff --git a/src/com/android/settings/homepage/HomepageManager.java b/src/com/android/settings/homepage/ContextualCardManager.java similarity index 56% rename from src/com/android/settings/homepage/HomepageManager.java rename to src/com/android/settings/homepage/ContextualCardManager.java index 61d7ce7c713..255f7a218a6 100644 --- a/src/com/android/settings/homepage/HomepageManager.java +++ b/src/com/android/settings/homepage/ContextualCardManager.java @@ -26,37 +26,37 @@ import java.util.ArrayList; import java.util.List; /** - * This is a centralized manager of multiple {@link HomepageCardController}. + * This is a centralized manager of multiple {@link ContextualCardController}. * - * {@link HomepageManager} first loads data from {@link CardContentLoader} and gets back a list of - * {@link HomepageCard}. All subclasses of {@link HomepageCardController} are loaded here, which - * will then trigger the {@link HomepageCardController} to load its data and listen to - * corresponding changes. When every single {@link HomepageCardController} updates its data, the + * {@link ContextualCardManager} first loads data from {@link CardContentLoader} and gets back a list of + * {@link ContextualCard}. All subclasses of {@link ContextualCardController} are loaded here, which + * will then trigger the {@link ContextualCardController} to load its data and listen to + * corresponding changes. When every single {@link ContextualCardController} updates its data, the * data will be passed here, then going through some sorting mechanisms. The - * {@link HomepageCardController} will end up building a list of {@link HomepageCard} for {@link - * HomepageAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to get the page + * {@link ContextualCardController} will end up building a list of {@link ContextualCard} for {@link + * ContextualCardsAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to get the page * refreshed. */ -public class HomepageManager implements CardContentLoader.CardContentLoaderListener, - HomepageCardUpdateListener { +public class ContextualCardManager implements CardContentLoader.CardContentLoaderListener, + ContextualCardUpdateListener { - private static final String TAG = "HomepageManager"; + private static final String TAG = "ContextualCardManager"; //The list for Settings Custom Card - @HomepageCard.CardType - private static final int[] SETTINGS_CARDS = {HomepageCard.CardType.CONDITIONAL}; + @ContextualCard.CardType + private static final int[] SETTINGS_CARDS = {ContextualCard.CardType.CONDITIONAL}; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; - private List mHomepageCards; - private HomepageCardUpdateListener mListener; + private List mContextualCards; + private ContextualCardUpdateListener mListener; - public HomepageManager(Context context, Lifecycle lifecycle) { + public ContextualCardManager(Context context, Lifecycle lifecycle) { mContext = context; mLifecycle = lifecycle; - mHomepageCards = new ArrayList<>(); + mContextualCards = new ArrayList<>(); mControllerRendererPool = new ControllerRendererPool(); } @@ -66,8 +66,8 @@ public class HomepageManager implements CardContentLoader.CardContentLoaderListe } private void loadCardControllers() { - if (mHomepageCards != null) { - for (HomepageCard card : mHomepageCards) { + if (mContextualCards != null) { + for (ContextualCard card : mContextualCards) { setupController(card.getCardType()); } } @@ -79,10 +79,10 @@ public class HomepageManager implements CardContentLoader.CardContentLoaderListe } private void setupController(int cardType) { - final HomepageCardController controller = mControllerRendererPool.getController(mContext, + final ContextualCardController controller = mControllerRendererPool.getController(mContext, cardType); if (controller != null) { - controller.setHomepageCardUpdateListener(this); + controller.setCardUpdateListener(this); if (controller instanceof LifecycleObserver) { if (mLifecycle != null) { mLifecycle.addObserver((LifecycleObserver) controller); @@ -93,35 +93,35 @@ public class HomepageManager implements CardContentLoader.CardContentLoaderListe //TODO(b/111822376): implement sorting mechanism. private void sortCards() { - //take mHomepageCards as the source and do the ranking based on the rule. + //take mContextualCards as the source and do the ranking based on the rule. } @Override - public void onHomepageCardUpdated(int cardType, List updateList) { + public void onHomepageCardUpdated(int cardType, List updateList) { //TODO(b/112245748): Should implement a DiffCallback. //Keep the old list for comparison. - final List prevCards = mHomepageCards; + final List prevCards = mContextualCards; //Remove the existing data that matches the certain cardType so as to insert the new data. - for (int i = mHomepageCards.size() - 1; i >= 0; i--) { - if (mHomepageCards.get(i).getCardType() == cardType) { - mHomepageCards.remove(i); + for (int i = mContextualCards.size() - 1; i >= 0; i--) { + if (mContextualCards.get(i).getCardType() == cardType) { + mContextualCards.remove(i); } } //Append the new data - mHomepageCards.addAll(updateList); + mContextualCards.addAll(updateList); sortCards(); if (mListener != null) { - mListener.onHomepageCardUpdated(HomepageCard.CardType.INVALID, mHomepageCards); + mListener.onHomepageCardUpdated(ContextualCard.CardType.INVALID, mContextualCards); } } @Override - public void onFinishCardLoading(List homepageCards) { - mHomepageCards = homepageCards; + public void onFinishCardLoading(List contextualCards) { + mContextualCards = contextualCards; //Force card sorting here in case CardControllers of custom view have nothing to update // for the first launch. @@ -130,7 +130,7 @@ public class HomepageManager implements CardContentLoader.CardContentLoaderListe loadCardControllers(); } - void setListener(HomepageCardUpdateListener listener) { + void setListener(ContextualCardUpdateListener listener) { mListener = listener; } diff --git a/src/com/android/settings/homepage/HomepageCardRenderer.java b/src/com/android/settings/homepage/ContextualCardRenderer.java similarity index 76% rename from src/com/android/settings/homepage/HomepageCardRenderer.java rename to src/com/android/settings/homepage/ContextualCardRenderer.java index ffa54e36a69..94fdb438f9e 100644 --- a/src/com/android/settings/homepage/HomepageCardRenderer.java +++ b/src/com/android/settings/homepage/ContextualCardRenderer.java @@ -21,9 +21,9 @@ import android.view.View; import androidx.recyclerview.widget.RecyclerView; /** - * UI renderer for {@link HomepageCard}. + * UI renderer for {@link ContextualCard}. */ -public interface HomepageCardRenderer { +public interface ContextualCardRenderer { /** * The layout type of the controller. @@ -31,16 +31,16 @@ public interface HomepageCardRenderer { int getViewType(); /** - * When {@link HomepageAdapter} calls {@link HomepageAdapter#onCreateViewHolder(ViewGroup, + * When {@link ContextualCardsAdapter} calls {@link ContextualCardsAdapter#onCreateViewHolder(ViewGroup, * int)}, this method will be called to retrieve the corresponding * {@link androidx.recyclerview.widget.RecyclerView.ViewHolder}. */ RecyclerView.ViewHolder createViewHolder(View view); /** - * When {@link HomepageAdapter} calls {@link HomepageAdapter#onBindViewHolder(RecyclerView + * When {@link ContextualCardsAdapter} calls {@link ContextualCardsAdapter#onBindViewHolder(RecyclerView * .ViewHolder, int)}, this method will be called to bind data to the * {@link androidx.recyclerview.widget.RecyclerView.ViewHolder}. */ - void bindView(RecyclerView.ViewHolder holder, HomepageCard card); + void bindView(RecyclerView.ViewHolder holder, ContextualCard card); } \ No newline at end of file diff --git a/src/com/android/settings/homepage/HomepageCardUpdateListener.java b/src/com/android/settings/homepage/ContextualCardUpdateListener.java similarity index 59% rename from src/com/android/settings/homepage/HomepageCardUpdateListener.java rename to src/com/android/settings/homepage/ContextualCardUpdateListener.java index 35bc3a34bf1..0b454260081 100644 --- a/src/com/android/settings/homepage/HomepageCardUpdateListener.java +++ b/src/com/android/settings/homepage/ContextualCardUpdateListener.java @@ -19,13 +19,13 @@ package com.android.settings.homepage; import java.util.List; /** - * When {@link HomepageCardController} detects changes, it will notify the listeners registered. In - * our case, {@link HomepageManager} gets noticed. + * When {@link ContextualCardController} detects changes, it will notify the listeners registered. In + * our case, {@link ContextualCardManager} gets noticed. * - * After the list of {@link HomepageCard} gets updated in{@link HomepageManager}, - * {@link HomepageManager} will notify the listeners registered, {@link HomepageAdapter} in this + * After the list of {@link ContextualCard} gets updated in{@link ContextualCardManager}, + * {@link ContextualCardManager} will notify the listeners registered, {@link ContextualCardsAdapter} in this * case. */ -public interface HomepageCardUpdateListener { - void onHomepageCardUpdated(int cardType, List updateList); +public interface ContextualCardUpdateListener { + void onHomepageCardUpdated(int cardType, List updateList); } \ No newline at end of file diff --git a/src/com/android/settings/homepage/HomepageAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java similarity index 72% rename from src/com/android/settings/homepage/HomepageAdapter.java rename to src/com/android/settings/homepage/ContextualCardsAdapter.java index bd376012223..254f4a4b440 100644 --- a/src/com/android/settings/homepage/HomepageAdapter.java +++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java @@ -27,39 +27,39 @@ import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; -public class HomepageAdapter extends RecyclerView.Adapter implements - HomepageCardUpdateListener { +public class ContextualCardsAdapter extends RecyclerView.Adapter implements + ContextualCardUpdateListener { static final int SPAN_COUNT = 2; - private static final String TAG = "HomepageAdapter"; + private static final String TAG = "ContextualCardsAdapter"; private static final int HALF_WIDTH = 1; private static final int FULL_WIDTH = 2; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; - private List mHomepageCards; + private List mContextualCards; - public HomepageAdapter(Context context, HomepageManager manager) { + public ContextualCardsAdapter(Context context, ContextualCardManager manager) { mContext = context; - mHomepageCards = new ArrayList<>(); + mContextualCards = new ArrayList<>(); mControllerRendererPool = manager.getControllerRendererPool(); setHasStableIds(true); } @Override public long getItemId(int position) { - return mHomepageCards.get(position).hashCode(); + return mContextualCards.get(position).hashCode(); } @Override public int getItemViewType(int position) { - return mHomepageCards.get(position).getCardType(); + return mContextualCards.get(position).getCardType(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int cardType) { - final HomepageCardRenderer renderer = mControllerRendererPool.getRenderer(mContext, + final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext, cardType); final int viewType = renderer.getViewType(); final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false); @@ -69,16 +69,16 @@ public class HomepageAdapter extends RecyclerView.Adapter homepageCards) { + public void onHomepageCardUpdated(int cardType, List contextualCards) { //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged() // instead. - if (homepageCards == null) { - mHomepageCards.clear(); + if (contextualCards == null) { + mContextualCards.clear(); } else { - mHomepageCards = homepageCards; + mContextualCards = contextualCards; } notifyDataSetChanged(); } diff --git a/src/com/android/settings/homepage/ControllerRendererPool.java b/src/com/android/settings/homepage/ControllerRendererPool.java index ebd63d4ff9b..1e4b37c24e5 100644 --- a/src/com/android/settings/homepage/ControllerRendererPool.java +++ b/src/com/android/settings/homepage/ControllerRendererPool.java @@ -21,77 +21,77 @@ import android.util.Log; import androidx.collection.ArraySet; -import com.android.settings.homepage.conditional.ConditionHomepageCardController; -import com.android.settings.homepage.conditional.ConditionHomepageCardRenderer; +import com.android.settings.homepage.conditional.ConditionContextualCardController; +import com.android.settings.homepage.conditional.ConditionContextualCardRenderer; import java.util.Set; /** - * This is a fragment scoped singleton holding a set of {@link HomepageCardController} and - * {@link HomepageCardRenderer}. + * This is a fragment scoped singleton holding a set of {@link ContextualCardController} and + * {@link ContextualCardRenderer}. */ public class ControllerRendererPool { private static final String TAG = "ControllerRendererPool"; - private final Set mControllers; - private final Set mRenderers; + private final Set mControllers; + private final Set mRenderers; public ControllerRendererPool() { mControllers = new ArraySet<>(); mRenderers = new ArraySet<>(); } - public T getController(Context context, - @HomepageCard.CardType int cardType) { - final Class clz = - HomepageCardLookupTable.getCardControllerClass(cardType); - for (HomepageCardController controller : mControllers) { + public T getController(Context context, + @ContextualCard.CardType int cardType) { + final Class clz = + ContextualCardLookupTable.getCardControllerClass(cardType); + for (ContextualCardController controller : mControllers) { if (controller.getClass() == clz) { Log.d(TAG, "Controller is already there."); return (T) controller; } } - final HomepageCardController controller = createCardController(context, clz); + final ContextualCardController controller = createCardController(context, clz); if (controller != null) { mControllers.add(controller); } return (T) controller; } - public Set getControllers() { + public Set getControllers() { return mControllers; } - public HomepageCardRenderer getRenderer(Context context, @HomepageCard.CardType int cardType) { - final Class clz = - HomepageCardLookupTable.getCardRendererClasses(cardType); - for (HomepageCardRenderer renderer : mRenderers) { + public ContextualCardRenderer getRenderer(Context context, @ContextualCard.CardType int cardType) { + final Class clz = + ContextualCardLookupTable.getCardRendererClasses(cardType); + for (ContextualCardRenderer renderer : mRenderers) { if (renderer.getClass() == clz) { Log.d(TAG, "Renderer is already there."); return renderer; } } - final HomepageCardRenderer renderer = createCardRenderer(context, clz); + final ContextualCardRenderer renderer = createCardRenderer(context, clz); if (renderer != null) { mRenderers.add(renderer); } return renderer; } - private HomepageCardController createCardController(Context context, - Class clz) { - if (ConditionHomepageCardController.class == clz) { - return new ConditionHomepageCardController(context); + private ContextualCardController createCardController(Context context, + Class clz) { + if (ConditionContextualCardController.class == clz) { + return new ConditionContextualCardController(context); } return null; } - private HomepageCardRenderer createCardRenderer(Context context, Class clz) { - if (ConditionHomepageCardRenderer.class == clz) { - return new ConditionHomepageCardRenderer(context, this /*controllerRendererPool*/); + private ContextualCardRenderer createCardRenderer(Context context, Class clz) { + if (ConditionContextualCardRenderer.class == clz) { + return new ConditionContextualCardRenderer(context, this /*controllerRendererPool*/); } return null; } diff --git a/src/com/android/settings/homepage/PersonalSettingsFragment.java b/src/com/android/settings/homepage/PersonalSettingsFragment.java index 1894e5e3696..69af23be2c8 100644 --- a/src/com/android/settings/homepage/PersonalSettingsFragment.java +++ b/src/com/android/settings/homepage/PersonalSettingsFragment.java @@ -16,7 +16,7 @@ package com.android.settings.homepage; -import static com.android.settings.homepage.HomepageAdapter.SPAN_COUNT; +import static com.android.settings.homepage.ContextualCardsAdapter.SPAN_COUNT; import android.os.Bundle; import android.view.LayoutInflater; @@ -36,17 +36,15 @@ public class PersonalSettingsFragment extends InstrumentedFragment { private static final String TAG = "PersonalSettingsFragment"; private RecyclerView mCardsContainer; - //TODO(b/113966426): rename - private HomepageAdapter mHomepageAdapter; private GridLayoutManager mLayoutManager; - //TODO(b/113966426): rename - private HomepageManager mHomepageManager; + private ContextualCardsAdapter mContextualCardsAdapter; + private ContextualCardManager mContextualCardManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mHomepageManager = new HomepageManager(getContext(), getSettingsLifecycle()); - mHomepageManager.startCardContentLoading(); + mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle()); + mContextualCardManager.startCardContentLoading(); } @Override @@ -58,9 +56,9 @@ public class PersonalSettingsFragment extends InstrumentedFragment { mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT, LinearLayoutManager.VERTICAL, false /* reverseLayout */); mCardsContainer.setLayoutManager(mLayoutManager); - mHomepageAdapter = new HomepageAdapter(getContext(), mHomepageManager); - mCardsContainer.setAdapter(mHomepageAdapter); - mHomepageManager.setListener(mHomepageAdapter); + mContextualCardsAdapter = new ContextualCardsAdapter(getContext(), mContextualCardManager); + mCardsContainer.setAdapter(mContextualCardsAdapter); + mContextualCardManager.setListener(mContextualCardsAdapter); return rootView; } diff --git a/src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java similarity index 55% rename from src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java rename to src/com/android/settings/homepage/conditional/ConditionContextualCardController.java index bb7af4b7084..eab6099fff3 100644 --- a/src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java +++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java @@ -18,9 +18,9 @@ package com.android.settings.homepage.conditional; import android.content.Context; -import com.android.settings.homepage.HomepageCard; -import com.android.settings.homepage.HomepageCardController; -import com.android.settings.homepage.HomepageCardUpdateListener; +import com.android.settings.homepage.ContextualCard; +import com.android.settings.homepage.ContextualCardController; +import com.android.settings.homepage.ContextualCardUpdateListener; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; @@ -32,32 +32,32 @@ import java.util.List; * This controller triggers the loading of conditional cards and monitors state changes to * update the homepage. */ -public class ConditionHomepageCardController implements HomepageCardController, ConditionListener, - LifecycleObserver, OnStart, OnStop { +public class ConditionContextualCardController implements ContextualCardController, + ConditionListener, LifecycleObserver, OnStart, OnStop { private final Context mContext; private final ConditionManager mConditionManager; - private HomepageCardUpdateListener mListener; + private ContextualCardUpdateListener mListener; - public ConditionHomepageCardController(Context context) { + public ConditionContextualCardController(Context context) { mContext = context; mConditionManager = new ConditionManager(context.getApplicationContext(), this); mConditionManager.startMonitoringStateChange(); } @Override - public void setHomepageCardUpdateListener(HomepageCardUpdateListener listener) { + public void setCardUpdateListener(ContextualCardUpdateListener listener) { mListener = listener; } @Override public int getCardType() { - return HomepageCard.CardType.CONDITIONAL; + return ContextualCard.CardType.CONDITIONAL; } @Override - public void onDataUpdated(List cardList) { + public void onDataUpdated(List cardList) { mListener.onHomepageCardUpdated(getCardType(), cardList); } @@ -72,34 +72,35 @@ public class ConditionHomepageCardController implements HomepageCardController, } @Override - public void onPrimaryClick(HomepageCard homepageCard) { - final ConditionCard card = (ConditionCard) homepageCard; + public void onPrimaryClick(ContextualCard contextualCard) { + final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard; mConditionManager.onPrimaryClick(mContext, card.getConditionId()); - } @Override - public void onActionClick(HomepageCard homepageCard) { - final ConditionCard card = (ConditionCard) homepageCard; + public void onActionClick(ContextualCard contextualCard) { + final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard; mConditionManager.onActionClick(card.getConditionId()); } @Override public void onConditionsChanged() { - final List conditionCards = new ArrayList<>(); + final List conditionCards = new ArrayList<>(); final List conditionList = mConditionManager.getDisplayableCards(); for (ConditionalCard condition : conditionList) { - final ConditionCard conditionCard = ((ConditionCard.Builder) new ConditionCard.Builder() - .setConditionId(condition.getId()) - .setMetricsConstant(condition.getMetricsConstant()) - .setActionText(condition.getActionText()) - .setName(mContext.getPackageName() + "/" + condition.getTitle().toString()) - .setCardType(HomepageCard.CardType.CONDITIONAL) - .setTitleText(condition.getTitle().toString()) - .setSummaryText(condition.getSummary().toString()) - .setIconDrawable(condition.getIcon())) - .build(); + final ContextualCard conditionCard = + new ConditionalContextualCard.Builder() + .setConditionId(condition.getId()) + .setMetricsConstant(condition.getMetricsConstant()) + .setActionText(condition.getActionText()) + .setName(mContext.getPackageName() + "/" + + condition.getTitle().toString()) + .setCardType(ContextualCard.CardType.CONDITIONAL) + .setTitleText(condition.getTitle().toString()) + .setSummaryText(condition.getSummary().toString()) + .setIconDrawable(condition.getIcon()) + .build(); conditionCards.add(conditionCard); } diff --git a/src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardRenderer.java similarity index 89% rename from src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java rename to src/com/android/settings/homepage/conditional/ConditionContextualCardRenderer.java index 6aa90ae558c..69988aeabdb 100644 --- a/src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java +++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardRenderer.java @@ -27,21 +27,21 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; +import com.android.settings.homepage.ContextualCard; import com.android.settings.homepage.ControllerRendererPool; -import com.android.settings.homepage.HomepageCard; -import com.android.settings.homepage.HomepageCardRenderer; +import com.android.settings.homepage.ContextualCardRenderer; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; /** - * Card renderer for {@link ConditionCard}. + * Card renderer for {@link ConditionalContextualCard}. */ -public class ConditionHomepageCardRenderer implements HomepageCardRenderer { +public class ConditionContextualCardRenderer implements ContextualCardRenderer { private final Context mContext; private final ControllerRendererPool mControllerRendererPool; - public ConditionHomepageCardRenderer(Context context, + public ConditionContextualCardRenderer(Context context, ControllerRendererPool controllerRendererPool) { mContext = context; mControllerRendererPool = controllerRendererPool; @@ -58,9 +58,9 @@ public class ConditionHomepageCardRenderer implements HomepageCardRenderer { } @Override - public void bindView(RecyclerView.ViewHolder holder, HomepageCard homepageCard) { + public void bindView(RecyclerView.ViewHolder holder, ContextualCard contextualCard) { final ConditionalCardHolder view = (ConditionalCardHolder) holder; - final ConditionCard card = (ConditionCard) homepageCard; + final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard; final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory( mContext).getMetricsFeatureProvider(); @@ -71,7 +71,7 @@ public class ConditionHomepageCardRenderer implements HomepageCardRenderer { initializeActionButton(view, card, metricsFeatureProvider); } - private void initializePrimaryClick(ConditionalCardHolder view, ConditionCard card, + private void initializePrimaryClick(ConditionalCardHolder view, ConditionalContextualCard card, MetricsFeatureProvider metricsFeatureProvider) { view.itemView.findViewById(R.id.content).setOnClickListener( v -> { @@ -83,7 +83,7 @@ public class ConditionHomepageCardRenderer implements HomepageCardRenderer { }); } - private void initializeView(ConditionalCardHolder view, ConditionCard card) { + private void initializeView(ConditionalCardHolder view, ConditionalContextualCard card) { view.icon.setImageDrawable(card.getIconDrawable()); view.title.setText(card.getTitleText()); view.summary.setText(card.getSummaryText()); @@ -91,7 +91,7 @@ public class ConditionHomepageCardRenderer implements HomepageCardRenderer { setViewVisibility(view.itemView, R.id.divider, false); } - private void initializeActionButton(ConditionalCardHolder view, ConditionCard card, + private void initializeActionButton(ConditionalCardHolder view, ConditionalContextualCard card, MetricsFeatureProvider metricsFeatureProvider) { final CharSequence action = card.getActionText(); final boolean hasButtons = !TextUtils.isEmpty(action); diff --git a/src/com/android/settings/homepage/conditional/ConditionCard.java b/src/com/android/settings/homepage/conditional/ConditionalContextualCard.java similarity index 81% rename from src/com/android/settings/homepage/conditional/ConditionCard.java rename to src/com/android/settings/homepage/conditional/ConditionalContextualCard.java index 9f445b2afd6..62a4956efcd 100644 --- a/src/com/android/settings/homepage/conditional/ConditionCard.java +++ b/src/com/android/settings/homepage/conditional/ConditionalContextualCard.java @@ -16,21 +16,21 @@ package com.android.settings.homepage.conditional; -import com.android.settings.homepage.HomepageCard; +import com.android.settings.homepage.ContextualCard; /** - * Data class representing a {@link ConditionCard}. + * Data class representing a conditional {@link ContextualCard}. * - * Use this class to store additional attributes on top of {@link HomepageCard} for + * Use this class to store additional attributes on top of {@link ContextualCard} for * {@link ConditionalCard}. */ -public class ConditionCard extends HomepageCard { +public class ConditionalContextualCard extends ContextualCard { private final long mConditionId; private final int mMetricsConstant; private final CharSequence mActionText; - private ConditionCard(Builder builder) { + private ConditionalContextualCard(Builder builder) { super(builder); mConditionId = builder.mConditionId; @@ -50,7 +50,7 @@ public class ConditionCard extends HomepageCard { return mActionText; } - static class Builder extends HomepageCard.Builder { + static class Builder extends ContextualCard.Builder { private long mConditionId; private int mMetricsConstant; @@ -71,8 +71,8 @@ public class ConditionCard extends HomepageCard { return this; } - public ConditionCard build() { - return new ConditionCard(this); + public ConditionalContextualCard build() { + return new ConditionalContextualCard(this); } } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardControllerTest.java similarity index 91% rename from tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java rename to tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardControllerTest.java index 2b8ab00e796..ed45ce7480d 100644 --- a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardControllerTest.java @@ -26,7 +26,7 @@ import android.content.Context; import android.graphics.drawable.Drawable; import com.android.settings.R; -import com.android.settings.homepage.HomepageCardUpdateListener; +import com.android.settings.homepage.ContextualCardUpdateListener; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; @@ -41,20 +41,20 @@ import java.util.ArrayList; import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) -public class ConditionHomepageCardControllerTest { +public class ConditionContextualCardControllerTest { @Mock private ConditionManager mConditionManager; @Mock - private HomepageCardUpdateListener mListener; + private ContextualCardUpdateListener mListener; private Context mContext; - private ConditionHomepageCardController mController; + private ConditionContextualCardController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); - mController = spy(new ConditionHomepageCardController(mContext)); + mController = spy(new ConditionContextualCardController(mContext)); ReflectionHelpers.setField(mController, "mConditionManager", mConditionManager); } @@ -78,7 +78,7 @@ public class ConditionHomepageCardControllerTest { final List conditionalCards = new ArrayList<>(); conditionalCards.add(fakeConditionalCard); when(mConditionManager.getDisplayableCards()).thenReturn(conditionalCards); - mController.setHomepageCardUpdateListener(mListener); + mController.setCardUpdateListener(mListener); mController.onConditionsChanged(); diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardRendererTest.java similarity index 79% rename from tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java rename to tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardRendererTest.java index 663931a2eb0..1ee052d20d2 100644 --- a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java +++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardRendererTest.java @@ -31,8 +31,8 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; +import com.android.settings.homepage.ContextualCard; import com.android.settings.homepage.ControllerRendererPool; -import com.android.settings.homepage.HomepageCard; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; @@ -43,20 +43,20 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; @RunWith(SettingsRobolectricTestRunner.class) -public class ConditionHomepageCardRendererTest { +public class ConditionContextualCardRendererTest { @Mock private ControllerRendererPool mControllerRendererPool; @Mock - private ConditionHomepageCardController mController; + private ConditionContextualCardController mController; private Context mContext; - private ConditionHomepageCardRenderer mRenderer; + private ConditionContextualCardRenderer mRenderer; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); - mRenderer = new ConditionHomepageCardRenderer(mContext, mControllerRendererPool); + mRenderer = new ConditionContextualCardRenderer(mContext, mControllerRendererPool); } @Test @@ -68,9 +68,9 @@ public class ConditionHomepageCardRendererTest { final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); final View card = view.findViewById(R.id.content); when(mControllerRendererPool.getController(mContext, - HomepageCard.CardType.CONDITIONAL)).thenReturn(mController); + ContextualCard.CardType.CONDITIONAL)).thenReturn(mController); - mRenderer.bindView(viewHolder, getHomepageCard()); + mRenderer.bindView(viewHolder, buildConditionContextualCard()); assertThat(card).isNotNull(); assertThat(card.hasOnClickListeners()).isTrue(); @@ -85,28 +85,27 @@ public class ConditionHomepageCardRendererTest { final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); final View card = view.findViewById(R.id.content); when(mControllerRendererPool.getController(mContext, - HomepageCard.CardType.CONDITIONAL)).thenReturn(mController); + ContextualCard.CardType.CONDITIONAL)).thenReturn(mController); - mRenderer.bindView(viewHolder, getHomepageCard()); + mRenderer.bindView(viewHolder, buildConditionContextualCard()); assertThat(card).isNotNull(); card.performClick(); - verify(mController).onPrimaryClick(any(HomepageCard.class)); + verify(mController).onPrimaryClick(any(ContextualCard.class)); } - private HomepageCard getHomepageCard() { - ConditionCard conditionCard = ((ConditionCard.Builder) new ConditionCard.Builder() + private ContextualCard buildConditionContextualCard() { + return new ConditionalContextualCard.Builder() .setConditionId(123) .setMetricsConstant(1) .setActionText("test_action") .setName("test_name") - .setCardType(HomepageCard.CardType.CONDITIONAL) + .setCardType(ContextualCard.CardType.CONDITIONAL) .setTitleText("test_title") .setSummaryText("test_summary") .setIconDrawable(mContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp)) - .setIsHalfWidth(true)) + .setIsHalfWidth(true) .build(); - return conditionCard; } } From a85a29d63bb5f466fd2445d330e6f79dcc175bfc Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Thu, 6 Sep 2018 18:10:12 -0700 Subject: [PATCH 10/16] Dark mode setting name Bug: 109589240 Test: visual Change-Id: Ic23ceb58140f8afda5575aad219541f05532cebe --- res/values/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 6af9721c83c..6782804d80a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -9459,11 +9459,11 @@ System UI demo mode - - Night mode + + Dark mode - Set Night mode + Set Dark mode Quick settings developer tiles From 831768fffe8879727792af432edab0e090178a5e Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Thu, 6 Sep 2018 21:13:28 -0700 Subject: [PATCH 11/16] Fix imports on pi-dev-plus-aosp to fix build Change-Id: Ifa467eef0f9264348d657ceb8372990313b42fed Merged-In: I0b1a170967ddcce7f388603fd521f6ed1eeba30b --- .../settings/bluetooth/BluetoothPairingController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java index 4b9ffdad4eb..c39f1d9feb0 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingController.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java @@ -24,6 +24,8 @@ import android.util.Log; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; +import androidx.annotation.VisibleForTesting; + import com.android.settings.R; import com.android.settings.bluetooth.BluetoothPairingDialogFragment.BluetoothPairingDialogListener; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -31,8 +33,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothProfile; import java.util.Locale; -import android.support.annotation.VisibleForTesting; - /** * A controller used by {@link BluetoothPairingDialog} to manage connection state while we try to * pair with a bluetooth device. It includes methods that allow the From e4fe56e16101343a47c9a0d6e881d07d52ab70f8 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Fri, 7 Sep 2018 13:27:08 -0400 Subject: [PATCH 12/16] Fix settings crash on noti listener screen Test: manual Bug: 114417814 Change-Id: I053a62201d3e9a1066d16d4a494a0c13bebccaf7 --- src/com/android/settings/utils/ManagedServiceSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java index 6ee5e8e3ac0..d6deba60fb6 100644 --- a/src/com/android/settings/utils/ManagedServiceSettings.java +++ b/src/com/android/settings/utils/ManagedServiceSettings.java @@ -117,7 +117,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { CharSequence title = null; try { title = mPm.getApplicationInfoAsUser( - service.packageName, 0, getCurrentUser(managedProfileId)).loadLabel(mPm); + service.packageName, 0, UserHandle.myUserId()).loadLabel(mPm); } catch (PackageManager.NameNotFoundException e) { // unlikely, as we are iterating over live services. Log.e(TAG, "can't find package name", e); From cbacfc5753e8a9dfba22b273ddf0762ac8bfac52 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Fri, 7 Sep 2018 14:14:47 -0400 Subject: [PATCH 13/16] Fix settings crash if launched with null args Test: manual Change-Id: I81990d63606074fc670cc39471c91ee61a73f1fc Fixes: 73666426 --- .../NotificationSettingsBase.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java index d06b545869f..ed0b1235ef4 100644 --- a/src/com/android/settings/notification/NotificationSettingsBase.java +++ b/src/com/android/settings/notification/NotificationSettingsBase.java @@ -112,19 +112,22 @@ abstract public class NotificationSettingsBase extends DashboardFragment { mPkgInfo = findPackageInfo(mPkg, mUid); - mUserId = UserHandle.getUserId(mUid); - mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended( - mContext, mPkg, mUserId); + if (mPkgInfo != null) { + mUserId = UserHandle.getUserId(mUid); + mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended( + mContext, mPkg, mUserId); - loadChannel(); - loadAppRow(); - loadChannelGroup(); - collectConfigActivities(); - getSettingsLifecycle().addObserver(use(HeaderPreferenceController.class)); + loadChannel(); + loadAppRow(); + loadChannelGroup(); + collectConfigActivities(); - for (NotificationPreferenceController controller : mControllers) { - controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin); + getSettingsLifecycle().addObserver(use(HeaderPreferenceController.class)); + + for (NotificationPreferenceController controller : mControllers) { + controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin); + } } } From ea0b32d1edab5f6d81d9f17fc327258e56535dee Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 7 Sep 2018 11:06:44 -0700 Subject: [PATCH 14/16] Misc clean up - Rename a few more things from Homepage* to ContextualCard* - Fixed a wrong parameter that GridLayoutManager was using Test: rebuild Change-Id: I7986b1caf63158e876295de6d31dbbe05581664d --- .../homepage/ContextualCardManager.java | 23 +++++++++++-------- .../ContextualCardUpdateListener.java | 10 ++++---- .../homepage/ContextualCardsAdapter.java | 8 +++---- .../homepage/PersonalSettingsFragment.java | 6 ++--- .../ConditionContextualCardController.java | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/com/android/settings/homepage/ContextualCardManager.java b/src/com/android/settings/homepage/ContextualCardManager.java index 255f7a218a6..aa2f576ef11 100644 --- a/src/com/android/settings/homepage/ContextualCardManager.java +++ b/src/com/android/settings/homepage/ContextualCardManager.java @@ -28,14 +28,14 @@ import java.util.List; /** * This is a centralized manager of multiple {@link ContextualCardController}. * - * {@link ContextualCardManager} first loads data from {@link CardContentLoader} and gets back a list of - * {@link ContextualCard}. All subclasses of {@link ContextualCardController} are loaded here, which - * will then trigger the {@link ContextualCardController} to load its data and listen to + * {@link ContextualCardManager} first loads data from {@link CardContentLoader} and gets back a + * list of {@link ContextualCard}. All subclasses of {@link ContextualCardController} are loaded + * here, which will then trigger the {@link ContextualCardController} to load its data and listen to * corresponding changes. When every single {@link ContextualCardController} updates its data, the * data will be passed here, then going through some sorting mechanisms. The - * {@link ContextualCardController} will end up building a list of {@link ContextualCard} for {@link - * ContextualCardsAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to get the page - * refreshed. + * {@link ContextualCardController} will end up building a list of {@link ContextualCard} for + * {@link ContextualCardsAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to + * get the page refreshed. */ public class ContextualCardManager implements CardContentLoader.CardContentLoaderListener, ContextualCardUpdateListener { @@ -48,8 +48,8 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; + private final List mContextualCards; - private List mContextualCards; private ContextualCardUpdateListener mListener; @@ -97,7 +97,7 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade } @Override - public void onHomepageCardUpdated(int cardType, List updateList) { + public void onContextualCardUpdated(int cardType, List updateList) { //TODO(b/112245748): Should implement a DiffCallback. //Keep the old list for comparison. final List prevCards = mContextualCards; @@ -115,13 +115,16 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade sortCards(); if (mListener != null) { - mListener.onHomepageCardUpdated(ContextualCard.CardType.INVALID, mContextualCards); + mListener.onContextualCardUpdated(ContextualCard.CardType.INVALID, mContextualCards); } } @Override public void onFinishCardLoading(List contextualCards) { - mContextualCards = contextualCards; + mContextualCards.clear(); + if (contextualCards != null) { + mContextualCards.addAll(contextualCards); + } //Force card sorting here in case CardControllers of custom view have nothing to update // for the first launch. diff --git a/src/com/android/settings/homepage/ContextualCardUpdateListener.java b/src/com/android/settings/homepage/ContextualCardUpdateListener.java index 0b454260081..d307a8f563b 100644 --- a/src/com/android/settings/homepage/ContextualCardUpdateListener.java +++ b/src/com/android/settings/homepage/ContextualCardUpdateListener.java @@ -19,13 +19,13 @@ package com.android.settings.homepage; import java.util.List; /** - * When {@link ContextualCardController} detects changes, it will notify the listeners registered. In - * our case, {@link ContextualCardManager} gets noticed. + * When {@link ContextualCardController} detects changes, it will notify the listeners registered. + * In our case, {@link ContextualCardManager} gets noticed. * * After the list of {@link ContextualCard} gets updated in{@link ContextualCardManager}, - * {@link ContextualCardManager} will notify the listeners registered, {@link ContextualCardsAdapter} in this - * case. + * {@link ContextualCardManager} will notify the listeners registered, {@link + * ContextualCardsAdapter} in this case. */ public interface ContextualCardUpdateListener { - void onHomepageCardUpdated(int cardType, List updateList); + void onContextualCardUpdated(int cardType, List updateList); } \ No newline at end of file diff --git a/src/com/android/settings/homepage/ContextualCardsAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java index 254f4a4b440..e985343cd59 100644 --- a/src/com/android/settings/homepage/ContextualCardsAdapter.java +++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java @@ -37,8 +37,7 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter mContextualCards; + private final List mContextualCards; public ContextualCardsAdapter(Context context, ContextualCardManager manager) { mContext = context; @@ -102,13 +101,14 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter contextualCards) { + public void onContextualCardUpdated(int cardType, List contextualCards) { //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged() // instead. if (contextualCards == null) { mContextualCards.clear(); } else { - mContextualCards = contextualCards; + mContextualCards.clear(); + mContextualCards.addAll(contextualCards); } notifyDataSetChanged(); } diff --git a/src/com/android/settings/homepage/PersonalSettingsFragment.java b/src/com/android/settings/homepage/PersonalSettingsFragment.java index 69af23be2c8..2eb9663cfda 100644 --- a/src/com/android/settings/homepage/PersonalSettingsFragment.java +++ b/src/com/android/settings/homepage/PersonalSettingsFragment.java @@ -24,7 +24,6 @@ import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -50,11 +49,10 @@ public class PersonalSettingsFragment extends InstrumentedFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final View rootView = inflater.inflate(R.layout.settings_homepage, - container, false); + final View rootView = inflater.inflate(R.layout.settings_homepage, container, false); mCardsContainer = rootView.findViewById(R.id.card_container); mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT, - LinearLayoutManager.VERTICAL, false /* reverseLayout */); + GridLayoutManager.VERTICAL, false /* reverseLayout */); mCardsContainer.setLayoutManager(mLayoutManager); mContextualCardsAdapter = new ContextualCardsAdapter(getContext(), mContextualCardManager); mCardsContainer.setAdapter(mContextualCardsAdapter); diff --git a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java index eab6099fff3..6701cfd0196 100644 --- a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java +++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java @@ -58,7 +58,7 @@ public class ConditionContextualCardController implements ContextualCardControll @Override public void onDataUpdated(List cardList) { - mListener.onHomepageCardUpdated(getCardType(), cardList); + mListener.onContextualCardUpdated(getCardType(), cardList); } @Override From 44be9131b10a42033a461d34a2e2ddf4d333febf Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 7 Sep 2018 12:56:53 -0700 Subject: [PATCH 15/16] Open personal settings tab when launching homepage Change-Id: I341e1a128fda7db8f953f9a0800050cc007554c5 Fixes: 114441682 Test: manual/robotest --- AndroidManifest.xml | 4 +- .../android/settings/SettingsActivity.java | 1 + .../SettingsHomepageActivity.java | 28 +++++---- tests/robotests/res/values/themes.xml | 11 +++- .../SettingsHomepageActivityTest.java | 57 +++++++++++++++++++ .../SettingsRobolectricTestRunner.java | 2 + 6 files changed, 88 insertions(+), 15 deletions(-) rename src/com/android/settings/{ => homepage}/SettingsHomepageActivity.java (79%) create mode 100644 tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index aa3364fdfbd..c8d9afff9ef 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -124,7 +124,7 @@ android:value="true" /> - + android:targetActivity=".homepage.SettingsHomepageActivity"> diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index cde2aca820c..ffce321a453 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -62,6 +62,7 @@ import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.gateway.SettingsGateway; import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.dashboard.DashboardSummary; +import com.android.settings.homepage.SettingsHomepageActivity; import com.android.settings.homepage.TopLevelSettings; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.DeviceIndexFeatureProvider; diff --git a/src/com/android/settings/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java similarity index 79% rename from src/com/android/settings/SettingsHomepageActivity.java rename to src/com/android/settings/homepage/SettingsHomepageActivity.java index 77155e00000..35b45a4642a 100644 --- a/src/com/android/settings/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -14,32 +14,31 @@ * limitations under the License. */ -package com.android.settings; +package com.android.settings.homepage; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.FeatureFlagUtils; +import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import com.android.settings.R; import com.android.settings.core.FeatureFlags; import com.android.settings.core.SettingsBaseActivity; -import com.android.settings.dashboard.DashboardSummary; -import com.android.settings.homepage.PersonalSettingsFragment; -import com.android.settings.homepage.TopLevelSettings; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.search.SearchFeatureProvider; import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class SettingsHomepageActivity extends SettingsBaseActivity { + @VisibleForTesting + static final String PERSONAL_SETTINGS_TAG = "personal_settings"; private static final String ALL_SETTINGS_TAG = "all_settings"; - private static final String PERSONAL_SETTINGS_TAG = "personal_settings"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -63,25 +62,31 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { navigation.setOnNavigationItemSelectedListener(item -> { switch (item.getItemId()) { case R.id.homepage_personal_settings: - switchFragment(PersonalSettingsFragment.class.getName(), PERSONAL_SETTINGS_TAG, + switchFragment(new PersonalSettingsFragment(), PERSONAL_SETTINGS_TAG, ALL_SETTINGS_TAG); return true; case R.id.homepage_all_settings: - switchFragment(TopLevelSettings.class.getName(), ALL_SETTINGS_TAG, + switchFragment(new TopLevelSettings(), ALL_SETTINGS_TAG, PERSONAL_SETTINGS_TAG); return true; } return false; }); + + if (savedInstanceState == null) { + // savedInstanceState is null, this is first load. + // Default to open contextual cards. + switchFragment(new PersonalSettingsFragment(), PERSONAL_SETTINGS_TAG, + ALL_SETTINGS_TAG); + } } public static boolean isDynamicHomepageEnabled(Context context) { return FeatureFlagUtils.isEnabled(context, FeatureFlags.DYNAMIC_HOMEPAGE); } - private void switchFragment(String fragmentName, String showFragmentTag, - String hideFragmentTag) { + private void switchFragment(Fragment fragment, String showFragmentTag, String hideFragmentTag) { final FragmentManager fragmentManager = getSupportFragmentManager(); final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); @@ -92,8 +97,7 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { Fragment showFragment = fragmentManager.findFragmentByTag(showFragmentTag); if (showFragment == null) { - showFragment = Fragment.instantiate(this, fragmentName, null /* args */); - fragmentTransaction.add(R.id.main_content, showFragment, showFragmentTag); + fragmentTransaction.add(R.id.main_content, fragment, showFragmentTag); } else { fragmentTransaction.show(showFragment); } diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml index 9a247f6abd8..d3ba69fe292 100644 --- a/tests/robotests/res/values/themes.xml +++ b/tests/robotests/res/values/themes.xml @@ -6,5 +6,14 @@ - diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java new file mode 100644 index 00000000000..4b237a0e0ed --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java @@ -0,0 +1,57 @@ +/* + * 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.homepage; + +import static com.android.settings.homepage.SettingsHomepageActivity.PERSONAL_SETTINGS_TAG; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.util.FeatureFlagUtils; + +import androidx.fragment.app.Fragment; + +import com.android.settings.core.FeatureFlags; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class SettingsHomepageActivityTest { + + private Context mContext; + private SettingsHomepageActivity mActivity; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, true); + } + + @Test + public void launchHomepage_shouldOpenPersonalSettings() { + mActivity = Robolectric.setupActivity(SettingsHomepageActivity.class); + final Fragment fragment = mActivity.getSupportFragmentManager() + .findFragmentByTag(PERSONAL_SETTINGS_TAG); + + assertThat(fragment).isInstanceOf(PersonalSettingsFragment.class); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java index ad808fcd8db..1432ab1a78a 100644 --- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java +++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java @@ -85,6 +85,8 @@ public class SettingsRobolectricTestRunner extends RobolectricTestRunner { Fs.fromURL(new URL("file:frameworks/opt/setupwizard/library/recyclerview/res")), null)); paths.add(new ResourcePath(null, Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/")), null)); + paths.add(new ResourcePath(null, + Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/extras/material-design-x/com.google.android.material_material-nodeps/android_common/aar/res/")), null)); paths.add(new ResourcePath(null, Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.cardview_cardview-nodeps/android_common/aar/res")), null)); } catch (MalformedURLException e) { From e845b40f35c76dc00a8bb17daec2aed53c2ef963 Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Fri, 7 Sep 2018 14:08:49 -0700 Subject: [PATCH 16/16] Do not show AddUser if adding user is not allowed. - when multi user is enabled, we should keep the current visibility for AddUser preference, since earlier check has been done to update its visibility according to the add user capability. We should only set the visibility to false if multi user is disabled. Change-Id: I246e9242f255dbd57c5309b2d16c95d202607531 Fixes: 114241868 Test: make RunSettingsRoboTests --- .../android/settings/users/UserSettings.java | 2 +- .../settings/users/UserSettingsTest.java | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index 181ab9dabd5..5e961a6d20d 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -964,9 +964,9 @@ public class UserSettings extends SettingsPreferenceFragment mAddUserWhenLockedPreferenceController.getPreferenceKey()); mAddUserWhenLockedPreferenceController.updateState(addUserOnLockScreen); mMultiUserFooterPreferenceController.updateState(null /* preference */); - mAddUser.setVisible(mUserCaps.mUserSwitcherEnabled); mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled); if (!mUserCaps.mUserSwitcherEnabled) { + mAddUser.setVisible(false); return; } diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java index 41f48c6d01a..413d77154e3 100644 --- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java +++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -184,4 +185,31 @@ public class UserSettingsTest { assertThat(addUser.isEnabled()).isFalse(); } + + @Test + public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 1); + final RestrictedPreference addUser = mock(RestrictedPreference.class); + + mUserCapabilities.mCanAddUser = false; + mUserCapabilities.mDisallowAddUser = true; + mUserCapabilities.mUserSwitcherEnabled = true; + + ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager); + ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities); + ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable); + ReflectionHelpers.setField(mFragment, "mAddingUser", false); + mFragment.mMePreference = mMePreference; + mFragment.mUserListCategory = mock(PreferenceCategory.class); + mFragment.mAddUser = addUser; + + doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen(); + + mFragment.updateUserList(); + + verify(addUser, never()).setVisible(true); + + } + }