diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2d2f5843cf3..b69cac73ad3 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2959,6 +2959,17 @@ android:value="true" /> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml index dbdb91bec8c..e062dbaf080 100644 --- a/res/layout/homepage_slice_tile.xml +++ b/res/layout/homepage_slice_tile.xml @@ -30,8 +30,6 @@ android:id="@+id/slice_view" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/homepage_card_vertical_margin" - android:layout_marginTop="@dimen/homepage_card_vertical_margin" android:paddingStart="@dimen/homepage_card_padding_start" android:paddingEnd="@dimen/homepage_card_padding_end"/> diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml new file mode 100644 index 00000000000..cbdd53fce50 --- /dev/null +++ b/res/layout/panel_layout.xml @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/res/layout/settings_entity_header.xml b/res/layout/settings_entity_header.xml deleted file mode 100644 index 5f5fe004a99..00000000000 --- a/res/layout/settings_entity_header.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml index 7a84e32d61c..42b78b441cb 100644 --- a/res/layout/settings_homepage_container.xml +++ b/res/layout/settings_homepage_container.xml @@ -42,7 +42,9 @@ + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/homepage_card_side_margin" + android:layout_marginEnd="@dimen/homepage_card_side_margin"/> + + android:id="@+id/main_content" + android:layout_height="match_parent" + android:layout_width="match_parent"/> \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index 5dfc0b91e7c..f470610295f 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -121,9 +121,9 @@ #C14CE6 #0F9D58 #F15B8D - #5011C1 + #783BE5 #9E9E9E - #26459C + #3F5FBD #1A73E8 #2EC7DC #9FA8DA diff --git a/res/values/config.xml b/res/values/config.xml index d487f46321f..917f14d4d6a 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -150,4 +150,14 @@ com.android.settings.intelligence + + + + com.android.emergency + + + + android.settings.EDIT_EMERGENCY_INFO + + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 8f44c692952..075979d94e0 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -329,8 +329,8 @@ 24dp 8dp 2dp - 4dp - 8dp + 8dp + 4dp 16dp 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index d8d084d9422..9c69bd1ec14 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4131,7 +4131,6 @@ Not enough storage space. App doesn\u2019t exist. - App is copy-protected. Install location isn\u2019t valid. System updates can\u2019t be installed on external media. @@ -4578,22 +4577,24 @@ Combine channels when playing audio - + Default - + 10 seconds - + 30 seconds - + 1 minute - + 2 minutes - - Content Timeout - - Control Timeout - - Choose how long it takes before automatically disappearing messages go away.\nSome apps may not support this setting yet. + + Time to read + + Time to take action + + Choose how much time you want to read and take action on messages that automatically go away.\n\nSupport for this setting is up to each app. + + Choose how long to show messages that ask you to take action, but are visible only temporarily.\n\nNot all apps support this setting. Touch & hold delay @@ -10297,8 +10298,8 @@ Unavailable when connected to %1$s - - Medical info, emergency contacts + + Medical info, emergency contacts See more @@ -10320,6 +10321,12 @@ No connected devices + + Settings Panel + + + Internet Connectivity + Force desktop mode diff --git a/res/values/styles.xml b/res/values/styles.xml index cfc5fd3abb1..4be1bb3569e 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -331,23 +331,6 @@ ?android:attr/textColorSecondary - - - - - - + + diff --git a/res/xml/accessibility_content_timeout_settings.xml b/res/xml/accessibility_content_timeout_settings.xml index 51573c958e5..d4504495342 100644 --- a/res/xml/accessibility_content_timeout_settings.xml +++ b/res/xml/accessibility_content_timeout_settings.xml @@ -19,7 +19,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:key="accessibility_content_timeout_preference" - android:title="@string/accessibility_accessibility_content_timeout_preference_title" + android:title="@string/accessibility_content_timeout_preference_title" android:persistent="false" > @@ -111,8 +110,7 @@ - - - - - - diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml index 14ad180a937..7036d2736d3 100644 --- a/res/xml/app_storage_settings.xml +++ b/res/xml/app_storage_settings.xml @@ -34,7 +34,7 @@ android:selectable="false" android:layout="@layout/horizontal_preference" /> - @@ -78,7 +78,7 @@ android:layout="@layout/preference_category_no_label" settings:allowDividerAbove="false" settings:allowDividerBelow="false"> - diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml index 01114b6c543..6449e4bc16f 100644 --- a/res/xml/bluetooth_device_details_fragment.xml +++ b/res/xml/bluetooth_device_details_fragment.xml @@ -19,7 +19,7 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/device_details_title"> - - - diff --git a/res/xml/dream_fragment_overview.xml b/res/xml/dream_fragment_overview.xml index a6214d18a17..e4c2eb5365f 100644 --- a/res/xml/dream_fragment_overview.xml +++ b/res/xml/dream_fragment_overview.xml @@ -35,7 +35,7 @@ - diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml index 7165218ecbc..998a2f98794 100644 --- a/res/xml/my_device_info.xml +++ b/res/xml/my_device_info.xml @@ -21,7 +21,7 @@ android:key="my_device_info_pref_screen" android:title="@string/about_settings"> - - - - diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml index c854f777e32..12c7e214a3d 100644 --- a/res/xml/power_usage_detail.xml +++ b/res/xml/power_usage_detail.xml @@ -19,7 +19,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto"> - - diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index 48e1276bc39..14d8edaaa9e 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -21,7 +21,7 @@ android:title="@string/power_usage_summary_title" settings:keywords="@string/keywords_battery"> - + + + + + + + + + + + \ No newline at end of file diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml index 2bdfdc80e24..c202a6cdf29 100644 --- a/res/xml/security_settings_face.xml +++ b/res/xml/security_settings_face.xml @@ -55,7 +55,7 @@ android:title="@string/security_settings_face_settings_improve_face"> - diff --git a/res/xml/usb_details_fragment.xml b/res/xml/usb_details_fragment.xml index 5c1efcf19b5..4a6cefa261f 100644 --- a/res/xml/usb_details_fragment.xml +++ b/res/xml/usb_details_fragment.xml @@ -20,7 +20,7 @@ android:title="@string/usb_preference" android:key="usb_details_fragment"> - diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml index 4198b76fb2c..45e73490119 100644 --- a/res/xml/wifi_network_details_fragment.xml +++ b/res/xml/wifi_network_details_fragment.xml @@ -19,7 +19,7 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" settings:initialExpandedChildrenCount="5"> - - - diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml index e201b8722f9..d05bbd2735f 100644 --- a/res/xml/zen_mode_schedule_rule_settings.xml +++ b/res/xml/zen_mode_schedule_rule_settings.xml @@ -20,11 +20,11 @@ android:key="zen_mode_schedule_rule_settings" android:title="@string/zen_mode_automatic_rule_settings_page_title"> - - diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml index 20143080c4e..832150a034b 100644 --- a/res/xml/zen_mode_settings.xml +++ b/res/xml/zen_mode_settings.xml @@ -65,7 +65,7 @@ android:fragment="com.android.settings.notification.ZenModeAutomationSettings"/> - infos = mContext.getPackageManager().queryIntentActivities(intent, 0); return infos != null && !infos.isEmpty(); } @@ -82,4 +83,20 @@ public class EmergencyInfoPreferenceController extends AbstractPreferenceControl public String getPreferenceKey() { return KEY_EMERGENCY_INFO; } + + private String getIntentAction(Context context) { + if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SAFETY_HUB)) { + return context.getResources().getString(R.string.config_emergency_intent_action); + } + + return ACTION_EDIT_EMERGENCY_INFO; + } + + private String getPackageName(Context context) { + if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SAFETY_HUB)) { + return context.getResources().getString(R.string.config_emergency_package_name); + } + + return PACKAGE_NAME_EMERGENCY; + } } diff --git a/src/com/android/settings/accounts/RemoveAccountPreferenceController.java b/src/com/android/settings/accounts/RemoveAccountPreferenceController.java index 9770332e83b..06eddd324e8 100644 --- a/src/com/android/settings/accounts/RemoveAccountPreferenceController.java +++ b/src/com/android/settings/accounts/RemoveAccountPreferenceController.java @@ -39,13 +39,13 @@ import androidx.preference.PreferenceScreen; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.widget.LayoutPreference; import java.io.IOException; diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java index 841fb5150f8..61ce33d3dc1 100644 --- a/src/com/android/settings/applications/AppStorageSettings.java +++ b/src/com/android/settings/applications/AppStorageSettings.java @@ -58,6 +58,7 @@ import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.applications.ApplicationsState.Callbacks; import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource.AppStorageStats; +import com.android.settingslib.widget.LayoutPreference; import java.util.Collections; import java.util.List; diff --git a/src/com/android/settings/applications/LayoutPreference.java b/src/com/android/settings/applications/LayoutPreference.java deleted file mode 100644 index 9c3cfaf1f8d..00000000000 --- a/src/com/android/settings/applications/LayoutPreference.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2015 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.applications; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import androidx.core.content.res.TypedArrayUtils; -import androidx.preference.Preference; -import androidx.preference.PreferenceViewHolder; - -import com.android.settings.R; -import com.android.settings.Utils; - -public class LayoutPreference extends Preference { - - private final View.OnClickListener mClickListener = v -> performClick(v); - private boolean mAllowDividerAbove; - private boolean mAllowDividerBelow; - private View mRootView; - - public LayoutPreference(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs, 0 /* defStyleAttr */); - } - - public LayoutPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs, defStyleAttr); - } - - public LayoutPreference(Context context, int resource) { - this(context, LayoutInflater.from(context).inflate(resource, null, false)); - } - - public LayoutPreference(Context context, View view) { - super(context); - setView(view); - } - - private void init(Context context, AttributeSet attrs, int defStyleAttr) { - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference); - mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove, - R.styleable.Preference_allowDividerAbove, false); - mAllowDividerBelow = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerBelow, - R.styleable.Preference_allowDividerBelow, false); - a.recycle(); - - a = context.obtainStyledAttributes( - attrs, com.android.internal.R.styleable.Preference, defStyleAttr, 0); - int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout, - 0); - if (layoutResource == 0) { - throw new IllegalArgumentException("LayoutPreference requires a layout to be defined"); - } - a.recycle(); - - // Need to create view now so that findViewById can be called immediately. - final View view = LayoutInflater.from(getContext()) - .inflate(layoutResource, null, false); - setView(view); - } - - private void setView(View view) { - setLayoutResource(R.layout.layout_preference_frame); - final ViewGroup allDetails = view.findViewById(R.id.all_details); - if (allDetails != null) { - Utils.forceCustomPadding(allDetails, true /* additive padding */); - } - mRootView = view; - setShouldDisableView(false); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - holder.itemView.setOnClickListener(mClickListener); - - final boolean selectable = isSelectable(); - holder.itemView.setFocusable(selectable); - holder.itemView.setClickable(selectable); - holder.setDividerAllowedAbove(mAllowDividerAbove); - holder.setDividerAllowedBelow(mAllowDividerBelow); - - FrameLayout layout = (FrameLayout) holder.itemView; - layout.removeAllViews(); - ViewGroup parent = (ViewGroup) mRootView.getParent(); - if (parent != null) { - parent.removeView(mRootView); - } - layout.addView(mRootView); - } - - public T findViewById(int id) { - return mRootView.findViewById(id); - } - - public void setAllowDividerBelow(boolean allowed) { - mAllowDividerBelow = allowed; - } - - public boolean isAllowDividerBelow() { - return mAllowDividerBelow; - } -} \ No newline at end of file diff --git a/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java b/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java index 5f41ae0afeb..f65bb9be5fc 100644 --- a/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java @@ -23,8 +23,6 @@ import android.content.pm.PackageInfo; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.Utils; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.BasePreferenceController; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.applications.AppUtils; @@ -32,6 +30,7 @@ import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.widget.LayoutPreference; public class AppHeaderViewPreferenceController extends BasePreferenceController implements AppInfoDashboardFragment.Callback, LifecycleObserver, OnStart { diff --git a/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java index f710f2e3b18..23c01216f9f 100644 --- a/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java @@ -34,7 +34,6 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.applications.AppStoreUtil; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -42,6 +41,7 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu; import com.android.settingslib.core.lifecycle.events.OnOptionsItemSelected; import com.android.settingslib.core.lifecycle.events.OnPrepareOptionsMenu; +import com.android.settingslib.widget.LayoutPreference; import java.util.List; diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java index d1fdc48f38c..8e41eff37db 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java @@ -23,8 +23,8 @@ import android.widget.Button; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.widget.LayoutPreference; /** * Controller for the remove button. diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java index 1795c07a892..11bd1741ca6 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java @@ -25,13 +25,13 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; /** * This class adds a header with device name and status (connected/disconnected, etc.). diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderController.java index 0e1811d70ed..26b21a1faf7 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderController.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderController.java @@ -21,8 +21,8 @@ import android.content.Context; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.widget.EntityHeaderController; +import com.android.settingslib.widget.LayoutPreference; /** * This class adds a header with device name. diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java index fb730b8e044..39ecd7875d5 100644 --- a/src/com/android/settings/core/SubSettingLauncher.java +++ b/src/com/android/settings/core/SubSettingLauncher.java @@ -84,11 +84,6 @@ public class SubSettingLauncher { return this; } - public SubSettingLauncher setIsShortCut(boolean isShortCut) { - mLaunchRequest.isShortCut = isShortCut; - return this; - } - public SubSettingLauncher setArguments(Bundle arguments) { mLaunchRequest.arguments = arguments; return this; @@ -159,8 +154,6 @@ public class SubSettingLauncher { intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, mLaunchRequest.titleResId); intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, mLaunchRequest.title); - intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, - mLaunchRequest.isShortCut); intent.addFlags(mLaunchRequest.flags); return intent; } @@ -195,7 +188,6 @@ public class SubSettingLauncher { int titleResId; String titleResPackageName; CharSequence title; - boolean isShortCut; int sourceMetricsCategory = -100; int flags; Fragment mResultListener; diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java index 7a2f0c105f3..27fa9beb532 100644 --- a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java +++ b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java @@ -88,8 +88,6 @@ public class StorageWizardMoveProgress extends StorageWizardBase { return getString(R.string.move_error_device_admin); case PackageManager.MOVE_FAILED_DOESNT_EXIST: return getString(R.string.does_not_exist); - case PackageManager.MOVE_FAILED_FORWARD_LOCKED: - return getString(R.string.app_forward_locked); case PackageManager.MOVE_FAILED_INVALID_LOCATION: return getString(R.string.invalid_location); case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE: diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java index 8c6c5aea0c9..8b21f0d9633 100644 --- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java +++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java @@ -29,9 +29,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.accounts.EmergencyInfoPreferenceController; -import com.android.settings.applications.LayoutPreference; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.deviceinfo.BluetoothAddressPreferenceController; import com.android.settings.deviceinfo.BrandedAccountPreferenceController; import com.android.settings.deviceinfo.BuildNumberPreferenceController; @@ -53,6 +51,7 @@ import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.widget.LayoutPreference; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java index bf307b68b8d..2a21379c4bf 100644 --- a/src/com/android/settings/display/ColorModePreferenceFragment.java +++ b/src/com/android/settings/display/ColorModePreferenceFragment.java @@ -23,12 +23,12 @@ import androidx.preference.PreferenceScreen; import com.android.internal.app.ColorDisplayController; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.widget.CandidateInfo; +import com.android.settingslib.widget.LayoutPreference; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/com/android/settings/display/NightDisplayActivationPreferenceController.java b/src/com/android/settings/display/NightDisplayActivationPreferenceController.java index 706ac8539c8..35cb5edcf19 100644 --- a/src/com/android/settings/display/NightDisplayActivationPreferenceController.java +++ b/src/com/android/settings/display/NightDisplayActivationPreferenceController.java @@ -28,8 +28,8 @@ import androidx.preference.PreferenceScreen; import com.android.internal.app.ColorDisplayController; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.TogglePreferenceController; +import com.android.settingslib.widget.LayoutPreference; public class NightDisplayActivationPreferenceController extends TogglePreferenceController { diff --git a/src/com/android/settings/dream/StartNowPreferenceController.java b/src/com/android/settings/dream/StartNowPreferenceController.java index 5519a0efc49..9e45ea37372 100644 --- a/src/com/android/settings/dream/StartNowPreferenceController.java +++ b/src/com/android/settings/dream/StartNowPreferenceController.java @@ -23,10 +23,10 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.dream.DreamBackend; +import com.android.settingslib.widget.LayoutPreference; public class StartNowPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin { diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index ce9cabcf428..6ad50a981c8 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -39,7 +39,6 @@ import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; -import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.appinfo.AppButtonsPreferenceController; import com.android.settings.applications.appinfo.ButtonActionDialogFragment; import com.android.settings.core.InstrumentedPreferenceFragment; @@ -52,6 +51,7 @@ import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.utils.StringUtil; +import com.android.settingslib.widget.LayoutPreference; import java.util.ArrayList; import java.util.List; diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java index e5a2e5e0ca2..48f4cc13c43 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java @@ -30,7 +30,6 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.EntityHeaderController; @@ -38,6 +37,7 @@ import com.android.settingslib.Utils; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.widget.LayoutPreference; /** * Controller that update the battery header view diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index f7c31e58f40..85aa915b73e 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -39,7 +39,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.SubSettingLauncher; import com.android.settings.fuelgauge.batterytip.BatteryTipLoader; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; @@ -49,6 +48,7 @@ import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.utils.PowerUtil; import com.android.settingslib.utils.StringUtil; +import com.android.settingslib.widget.LayoutPreference; import java.util.Collections; import java.util.List; diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCard.java b/src/com/android/settings/homepage/contextualcards/ContextualCard.java index 4e4e34f282f..ca5555b855d 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCard.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCard.java @@ -33,13 +33,16 @@ public class ContextualCard { /** * Flags indicating the type of the ContextualCard. */ - @IntDef({CardType.DEFAULT, CardType.SLICE, CardType.LEGACY_SUGGESTION, CardType.CONDITIONAL}) + @IntDef({CardType.DEFAULT, CardType.SLICE, CardType.LEGACY_SUGGESTION, CardType.CONDITIONAL, + CardType.CONDITIONAL_HEADER, CardType.CONDITIONAL_FOOTER}) @Retention(RetentionPolicy.SOURCE) public @interface CardType { int DEFAULT = 0; int SLICE = 1; int LEGACY_SUGGESTION = 2; int CONDITIONAL = 3; + int CONDITIONAL_HEADER = 4; + int CONDITIONAL_FOOTER = 5; } private final Builder mBuilder; diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index c723cfd0245..4c06601a431 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -23,7 +23,6 @@ import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; -import android.content.pm.PackageManager; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; @@ -35,7 +34,6 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.slice.Slice; -import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice; import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice; import com.android.settings.wifi.WifiSlice; import com.android.settingslib.utils.AsyncLoaderCompat; @@ -52,11 +50,17 @@ public class ContextualCardLoader extends AsyncLoaderCompat private static final String TAG = "ContextualCardLoader"; - private Context mContext; + private final ContentObserver mObserver = new ContentObserver( + new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange) { + if (isStarted()) { + forceLoad(); + } + } + }; - public interface CardContentLoaderListener { - void onFinishCardLoading(List contextualCards); - } + private Context mContext; ContextualCardLoader(Context context) { super(context); @@ -86,9 +90,7 @@ public class ContextualCardLoader extends AsyncLoaderCompat public List loadInBackground() { final List result = new ArrayList<>(); try (Cursor cursor = getContextualCardsFromProvider()) { - if (cursor.getCount() == 0) { - result.addAll(createStaticCards()); - } else { + if (cursor.getCount() > 0) { for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { final ContextualCard card = new ContextualCard(cursor); if (card.isCustomCard()) { @@ -130,24 +132,6 @@ public class ContextualCardLoader extends AsyncLoaderCompat return CardDatabaseHelper.getInstance(mContext).getContextualCards(); } - @VisibleForTesting - List createStaticCards() { - final long appVersionCode = getAppVersionCode(); - final String packageName = mContext.getPackageName(); - final double rankingScore = 0.0; - final List result = new ArrayList(); - result.add(new ContextualCard.Builder() - .setSliceUri(BatterySlice.BATTERY_CARD_URI) - .setName(BatterySlice.PATH_BATTERY_INFO) - .setPackageName(packageName) - .setRankingScore(rankingScore) - .setAppVersion(appVersionCode) - .setCardType(ContextualCard.CardType.SLICE) - .setIsHalfWidth(false) - .build()); - return result; - } - @VisibleForTesting List filterEligibleCards(List candidates) { return candidates.stream().filter(card -> isCardEligibleToDisplay(card)) @@ -191,23 +175,7 @@ public class ContextualCardLoader extends AsyncLoaderCompat .count(); } - private long getAppVersionCode() { - try { - return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), - 0 /* flags */).getLongVersionCode(); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Invalid package name for context", e); - } - return -1L; + public interface CardContentLoaderListener { + void onFinishCardLoading(List contextualCards); } - - private final ContentObserver mObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange) { - if (isStarted()) { - forceLoad(); - } - } - }; -} +} \ No newline at end of file diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java index dabc88c67f6..a4a84199c98 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java @@ -24,10 +24,14 @@ import androidx.annotation.VisibleForTesting; import com.android.settings.homepage.contextualcards.ContextualCard.CardType; import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardController; import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer; +import com.android.settings.homepage.contextualcards.conditional + .ConditionHeaderContextualCardRenderer; import com.android.settings.homepage.contextualcards.legacysuggestion .LegacySuggestionContextualCardController; import com.android.settings.homepage.contextualcards.legacysuggestion .LegacySuggestionContextualCardRenderer; +import com.android.settings.homepage.contextualcards.conditional + .ConditionFooterContextualCardRenderer; import com.android.settings.homepage.contextualcards.slices.SliceContextualCardController; import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer; @@ -83,6 +87,14 @@ public class ContextualCardLookupTable { SliceContextualCardRenderer.VIEW_TYPE, SliceContextualCardController.class, SliceContextualCardRenderer.class)); + add(new ControllerRendererMapping(CardType.CONDITIONAL_FOOTER, + ConditionFooterContextualCardRenderer.VIEW_TYPE, + ConditionContextualCardController.class, + ConditionFooterContextualCardRenderer.class)); + add(new ControllerRendererMapping(CardType.CONDITIONAL_HEADER, + ConditionHeaderContextualCardRenderer.VIEW_TYPE, + ConditionContextualCardController.class, + ConditionHeaderContextualCardRenderer.class)); }}; public static Class getCardControllerClass( diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java index 0a8749d37d4..10bed90d601 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java @@ -129,5 +129,7 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter conditionCards = mConditionManager.getDisplayableCards(); + final Map> conditionalCards = + buildConditionalCardsWithFooterOrHeader(conditionCards); + mListener.onContextualCardUpdated(conditionalCards); - final boolean isOddNumber = conditionCards.size() % 2 == 1; + } + + /** + * According to conditional cards, build a map that includes conditional cards, header card and + * footer card. + * + * Rules: + * - The last one of conditional cards will be displayed as a full-width card if the size of + * conditional cards is odd number. The rest will be displayed as a half-width card. + * - By default conditional cards will be collapsed if there are more than TWO cards. + * + * For examples: + * - Only one conditional card: Returns a map that contains a full-width conditional card, + * no header card and no footer card. + *

Map{(CONDITIONAL, conditionCards), (CONDITIONAL_FOOTER, EMPTY_LIST), (CONDITIONAL_HEADER, + * EMPTY_LIST)}

+ * - Two conditional cards: Returns a map that contains two half-width conditional cards, + * no header card and no footer card. + *

Map{(CONDITIONAL, conditionCards), (CONDITIONAL_FOOTER, EMPTY_LIST), (CONDITIONAL_HEADER, + * EMPTY_LIST)}

+ * - Three conditional cards or above: By default, returns a map that contains no conditional + * card, one header card and no footer card. If conditional cards are expanded, will returns a + * map that contains three conditional cards, no header card and one footer card. + * If expanding conditional cards: + *

Map{(CONDITIONAL, conditionCards), (CONDITIONAL_FOOTER, footerCards), (CONDITIONAL_HEADER, + * EMPTY_LIST)}

+ * If collapsing conditional cards: + *

Map{(CONDITIONAL, EMPTY_LIST), (CONDITIONAL_FOOTER, EMPTY_LIST), (CONDITIONAL_HEADER, + * headerCards)}

+ * + * @param conditionCards A list of conditional cards that are from {@link + * ConditionManager#getDisplayableCards} + * @return A map contained three types of lists + */ + @VisibleForTesting + Map> buildConditionalCardsWithFooterOrHeader( + List conditionCards) { + final Map> conditionalCards = new ArrayMap<>(); + conditionalCards.put(ContextualCard.CardType.CONDITIONAL, + getExpandedConditionalCards(conditionCards)); + conditionalCards.put(ContextualCard.CardType.CONDITIONAL_FOOTER, + getConditionalFooterCard(conditionCards)); + conditionalCards.put(ContextualCard.CardType.CONDITIONAL_HEADER, + getConditionalHeaderCard(conditionCards)); + return conditionalCards; + } + + private List getExpandedConditionalCards(List conditionCards) { + if (conditionCards.isEmpty() || (conditionCards.size() > EXPANDING_THRESHOLD + && !mIsExpanded)) { + return Collections.EMPTY_LIST; + } + final List expandedCards = conditionCards.stream().collect( + Collectors.toList()); + final boolean isOddNumber = expandedCards.size() % 2 == 1; if (isOddNumber) { - final int lastIndex = conditionCards.size() - 1; - final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards - .get(lastIndex); - conditionCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build()); + final int lastIndex = expandedCards.size() - 1; + final ConditionalContextualCard card = + (ConditionalContextualCard) expandedCards.get(lastIndex); + expandedCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build()); } + return expandedCards; + } - if (mListener != null) { - final Map> conditionalCards = new ArrayMap<>(); - conditionalCards.put(ContextualCard.CardType.CONDITIONAL, conditionCards); - mListener.onContextualCardUpdated(conditionalCards); + private List getConditionalFooterCard(List conditionCards) { + if (!conditionCards.isEmpty() && mIsExpanded + && conditionCards.size() > EXPANDING_THRESHOLD) { + final List footerCards = new ArrayList<>(); + footerCards.add(new ConditionFooterContextualCard.Builder() + .setName(CONDITION_FOOTER) + .setRankingScore(UNSUPPORTED_RANKING) + .build()); + return footerCards; } + return Collections.EMPTY_LIST; + } + + private List getConditionalHeaderCard(List conditionCards) { + if (!conditionCards.isEmpty() && !mIsExpanded + && conditionCards.size() > EXPANDING_THRESHOLD) { + final List headerCards = new ArrayList<>(); + headerCards.add(new ConditionHeaderContextualCard.Builder() + .setConditionalCards(conditionCards) + .setName(CONDITION_HEADER) + .setRankingScore(UNSUPPORTED_RANKING) + .build()); + return headerCards; + } + return Collections.EMPTY_LIST; } } diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCard.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCard.java new file mode 100644 index 00000000000..17a5bfa45da --- /dev/null +++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCard.java @@ -0,0 +1,50 @@ +/* + * 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.contextualcards.conditional; + +import com.android.settings.homepage.contextualcards.ContextualCard; + +/** + * Data class representing a condition footer {@link ContextualCard}. + * + * Use this class for {@link ConditionFooterContextualCardRenderer} and + * {@link ConditionContextualCardController}. + */ +public class ConditionFooterContextualCard extends ContextualCard { + + private ConditionFooterContextualCard(Builder builder) { + super(builder); + } + + @Override + public int getCardType() { + return CardType.CONDITIONAL_FOOTER; + } + + public static class Builder extends ContextualCard.Builder { + + @Override + public Builder setCardType(int cardType) { + throw new IllegalArgumentException( + "Cannot change card type for " + getClass().getName()); + } + + public ConditionFooterContextualCard build() { + return new ConditionFooterContextualCard(this); + } + } +} \ No newline at end of file diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardRenderer.java new file mode 100644 index 00000000000..2465ca4ab75 --- /dev/null +++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardRenderer.java @@ -0,0 +1,79 @@ +/* + * 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.contextualcards.conditional; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.ContextualCardRenderer; +import com.android.settings.homepage.contextualcards.ControllerRendererPool; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; + +public class ConditionFooterContextualCardRenderer implements ContextualCardRenderer { + public static final int VIEW_TYPE = R.layout.homepage_condition_footer; + private static final String TAG = "ConditionFooterRenderer"; + + private final Context mContext; + private final ControllerRendererPool mControllerRendererPool; + + public ConditionFooterContextualCardRenderer(Context context, + ControllerRendererPool controllerRendererPool) { + mContext = context; + mControllerRendererPool = controllerRendererPool; + } + + @Override + public int getViewType(boolean isHalfWidth) { + return VIEW_TYPE; + } + + @Override + public RecyclerView.ViewHolder createViewHolder(View view) { + return new ConditionFooterCardHolder(view); + } + + @Override + public void bindView(RecyclerView.ViewHolder holder, ContextualCard card) { + final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory( + mContext).getMetricsFeatureProvider(); + holder.itemView.setOnClickListener(v -> { + metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN, + MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, + SettingsEnums.SETTINGS_HOMEPAGE, + null /* key */, + 0 /* false */); + final ConditionContextualCardController controller = + mControllerRendererPool.getController(mContext, + ContextualCard.CardType.CONDITIONAL_FOOTER); + controller.setIsExpanded(false); + controller.onConditionsChanged(); + }); + } + + public static class ConditionFooterCardHolder extends RecyclerView.ViewHolder { + public ConditionFooterCardHolder(View itemView) { + super(itemView); + } + } +} diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCard.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCard.java new file mode 100644 index 00000000000..b72f9f7e6af --- /dev/null +++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCard.java @@ -0,0 +1,88 @@ +/* + * 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.contextualcards.conditional; + +import android.text.TextUtils; + +import com.android.settings.homepage.contextualcards.ContextualCard; + +import java.util.List; +import java.util.Objects; + +/** + * Data class representing a condition header {@link ContextualCard}. + * + * Use this class to store additional attributes on top of {@link ContextualCard} for + * {@link ConditionHeaderContextualCardRenderer} and {@link ConditionContextualCardController}. + */ +public class ConditionHeaderContextualCard extends ContextualCard { + + private final List mConditionalCards; + + private ConditionHeaderContextualCard(Builder builder) { + super(builder); + mConditionalCards = builder.mConditionalCards; + } + + @Override + public int getCardType() { + return CardType.CONDITIONAL_HEADER; + } + + public List getConditionalCards() { + return mConditionalCards; + } + + @Override + public int hashCode() { + return Objects.hash(getName(), mConditionalCards); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ConditionHeaderContextualCard)) { + return false; + } + final ConditionHeaderContextualCard that = (ConditionHeaderContextualCard) obj; + + return TextUtils.equals(getName(), that.getName()) && mConditionalCards.equals( + that.mConditionalCards); + } + + public static class Builder extends ContextualCard.Builder { + + private List mConditionalCards; + + public Builder setConditionalCards(List conditionalCards) { + mConditionalCards = conditionalCards; + return this; + } + + @Override + public Builder setCardType(int cardType) { + throw new IllegalArgumentException( + "Cannot change card type for " + getClass().getName()); + } + + public ConditionHeaderContextualCard build() { + return new ConditionHeaderContextualCard(this); + } + } +} \ No newline at end of file diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRenderer.java new file mode 100644 index 00000000000..a98c82d4178 --- /dev/null +++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRenderer.java @@ -0,0 +1,97 @@ +/* + * 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.contextualcards.conditional; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.ContextualCardRenderer; +import com.android.settings.homepage.contextualcards.ControllerRendererPool; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; + +public class ConditionHeaderContextualCardRenderer implements ContextualCardRenderer { + public static final int VIEW_TYPE = R.layout.homepage_condition_header; + private static final String TAG = "ConditionHeaderRenderer"; + + private final Context mContext; + private final ControllerRendererPool mControllerRendererPool; + + public ConditionHeaderContextualCardRenderer(Context context, + ControllerRendererPool controllerRendererPool) { + mContext = context; + mControllerRendererPool = controllerRendererPool; + } + + @Override + public int getViewType(boolean isHalfWidth) { + return VIEW_TYPE; + } + + @Override + public RecyclerView.ViewHolder createViewHolder(View view) { + return new ConditionHeaderCardHolder(view); + } + + @Override + public void bindView(RecyclerView.ViewHolder holder, ContextualCard contextualCard) { + final ConditionHeaderContextualCard headerCard = + (ConditionHeaderContextualCard) contextualCard; + final ConditionHeaderCardHolder view = (ConditionHeaderCardHolder) holder; + final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory( + mContext).getMetricsFeatureProvider(); + view.icons.removeAllViews(); + headerCard.getConditionalCards().stream().forEach(card -> { + final ImageView icon = (ImageView) LayoutInflater.from(mContext).inflate( + R.layout.homepage_condition_header_icon, view.icons, false); + icon.setImageDrawable(card.getIconDrawable()); + view.icons.addView(icon); + }); + view.itemView.setOnClickListener(v -> { + metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN, + MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, + SettingsEnums.SETTINGS_HOMEPAGE, + null /* key */, + 1 /* true */); + final ConditionContextualCardController controller = + mControllerRendererPool.getController(mContext, + ContextualCard.CardType.CONDITIONAL_HEADER); + controller.setIsExpanded(true); + controller.onConditionsChanged(); + }); + } + + public static class ConditionHeaderCardHolder extends RecyclerView.ViewHolder { + public final LinearLayout icons; + public final ImageView expandIndicator; + + public ConditionHeaderCardHolder(View itemView) { + super(itemView); + icons = itemView.findViewById(R.id.header_icons_container); + expandIndicator = itemView.findViewById(R.id.expand_indicator); + } + } +} diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java index 80cca2c6412..1c4e3516a3d 100644 --- a/src/com/android/settings/network/AirplaneModePreferenceController.java +++ b/src/com/android/settings/network/AirplaneModePreferenceController.java @@ -93,7 +93,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public boolean isSliceable() { - return TextUtils.equals(getPreferenceKey(), "toggle_airplane"); + return true; } @Override diff --git a/src/com/android/settings/notification/BlockPreferenceController.java b/src/com/android/settings/notification/BlockPreferenceController.java index bee32f511a2..960526cb05b 100644 --- a/src/com/android/settings/notification/BlockPreferenceController.java +++ b/src/com/android/settings/notification/BlockPreferenceController.java @@ -27,9 +27,9 @@ import android.widget.Switch; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.SwitchBar; +import com.android.settingslib.widget.LayoutPreference; public class BlockPreferenceController extends NotificationPreferenceController implements PreferenceControllerMixin, SwitchBar.OnSwitchChangeListener { diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java index f0c860f3514..0c091b437a3 100644 --- a/src/com/android/settings/notification/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/HeaderPreferenceController.java @@ -31,10 +31,10 @@ import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; public class HeaderPreferenceController extends NotificationPreferenceController implements PreferenceControllerMixin, LifecycleObserver { diff --git a/src/com/android/settings/notification/NotificationSwitchBarPreference.java b/src/com/android/settings/notification/NotificationSwitchBarPreference.java index ff429879925..01c4f6ab468 100644 --- a/src/com/android/settings/notification/NotificationSwitchBarPreference.java +++ b/src/com/android/settings/notification/NotificationSwitchBarPreference.java @@ -22,9 +22,9 @@ import android.view.View; import androidx.preference.PreferenceViewHolder; -import com.android.settings.applications.LayoutPreference; import com.android.settings.widget.ToggleSwitch; import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.widget.LayoutPreference; public class NotificationSwitchBarPreference extends LayoutPreference { private ToggleSwitch mSwitch; diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java index 41eb1113e1b..72bb0e3d611 100644 --- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java +++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java @@ -28,17 +28,17 @@ import android.text.TextUtils; import android.util.Slog; import android.view.View; -import com.android.internal.logging.nano.MetricsProto; -import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settings.widget.EntityHeaderController; -import com.android.settingslib.core.lifecycle.Lifecycle; - import androidx.fragment.app.Fragment; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.widget.EntityHeaderController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; + public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModePreferenceController implements PreferenceControllerMixin { diff --git a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java index d4114026c16..f38deb35167 100644 --- a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java +++ b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java @@ -25,9 +25,9 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.widget.SwitchBar; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; public class ZenAutomaticRuleSwitchPreferenceController extends AbstractZenModeAutomaticRulePreferenceController implements diff --git a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java index 3e45899b2ed..8ebc6b8ab54 100644 --- a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java @@ -26,9 +26,9 @@ import androidx.preference.Preference; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; public class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController implements PreferenceControllerMixin { diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java index 38d48c83402..02468b8ad06 100644 --- a/src/com/android/settings/overlay/FeatureFactory.java +++ b/src/com/android/settings/overlay/FeatureFactory.java @@ -29,6 +29,7 @@ import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider; import com.android.settings.fuelgauge.PowerUsageFeatureProvider; import com.android.settings.gestures.AssistGestureFeatureProvider; import com.android.settings.localepicker.LocaleFeatureProvider; +import com.android.settings.panel.PanelFeatureProvider; import com.android.settings.search.SearchFeatureProvider; import com.android.settings.security.SecurityFeatureProvider; import com.android.settings.slices.SlicesFeatureProvider; @@ -105,6 +106,8 @@ public abstract class FeatureFactory { public abstract AccountFeatureProvider getAccountFeatureProvider(); + public abstract PanelFeatureProvider getPanelFeatureProvider(); + public static final class FactoryNotFoundException extends RuntimeException { public FactoryNotFoundException(Throwable throwable) { super("Unable to create factory. Did you misconfigure Proguard?", throwable); diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java index f74043f0264..8d6d4b69fb6 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.java +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java @@ -42,6 +42,8 @@ import com.android.settings.gestures.AssistGestureFeatureProvider; import com.android.settings.gestures.AssistGestureFeatureProviderImpl; import com.android.settings.localepicker.LocaleFeatureProvider; import com.android.settings.localepicker.LocaleFeatureProviderImpl; +import com.android.settings.panel.PanelFeatureProvider; +import com.android.settings.panel.PanelFeatureProviderImpl; import com.android.settings.search.SearchFeatureProvider; import com.android.settings.search.SearchFeatureProviderImpl; import com.android.settings.security.SecurityFeatureProvider; @@ -72,6 +74,7 @@ public class FeatureFactoryImpl extends FeatureFactory { private UserFeatureProvider mUserFeatureProvider; private SlicesFeatureProvider mSlicesFeatureProvider; private AccountFeatureProvider mAccountFeatureProvider; + private PanelFeatureProvider mPanelFeatureProvider; @Override public SupportFeatureProvider getSupportFeatureProvider(Context context) { @@ -209,4 +212,12 @@ public class FeatureFactoryImpl extends FeatureFactory { } return mAccountFeatureProvider; } + + @Override + public PanelFeatureProvider getPanelFeatureProvider() { + if (mPanelFeatureProvider == null) { + mPanelFeatureProvider = new PanelFeatureProviderImpl(); + } + return mPanelFeatureProvider; + } } diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java new file mode 100644 index 00000000000..b6fe53bcbfc --- /dev/null +++ b/src/com/android/settings/panel/InternetConnectivityPanel.java @@ -0,0 +1,77 @@ +/* + * 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.panel; + +import androidx.annotation.VisibleForTesting; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.provider.SettingsSlicesContract; + +import com.android.settings.R; +import com.android.settings.wifi.WifiSlice; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents the Internet Connectivity Panel. + * + *

+ * Displays Wifi (full Slice) and Airplane mode. + *

+ */ +public class InternetConnectivityPanel implements PanelContent { + + @VisibleForTesting + static final Uri AIRPLANE_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(SettingsSlicesContract.AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE) + .build(); + + private final Context mContext; + + public static InternetConnectivityPanel create(Context context) { + return new InternetConnectivityPanel(context); + } + + private InternetConnectivityPanel(Context context) { + mContext = context.getApplicationContext(); + } + + @Override + public String getTitle() { + return (String) mContext.getText(R.string.internet_connectivity_panel_title); + } + + @Override + public List getSlices() { + final List uris = new ArrayList<>(); + uris.add(WifiSlice.WIFI_URI); + uris.add(AIRPLANE_URI); + return uris; + } + + @Override + public Intent getSeeMoreIntent() { + return null; + } +} diff --git a/src/com/android/settings/panel/PanelContent.java b/src/com/android/settings/panel/PanelContent.java new file mode 100644 index 00000000000..bd84c2fa617 --- /dev/null +++ b/src/com/android/settings/panel/PanelContent.java @@ -0,0 +1,49 @@ +/* + * 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.panel; + +import android.content.Intent; +import android.net.Uri; + +import java.util.List; + +/** + * Represents the data class needed to create a Settings Panel. See {@link PanelFragment}. + */ +public interface PanelContent { + + /** + * @return a string for the title of the Panel. + */ + CharSequence getTitle(); + + /** + * @return an ordered list of the Slices to be displayed in the Panel. The first item in the + * list is shown on top of the Panel. + */ + List getSlices(); + + + /** + * @return an {@link Intent} to the full content in Settings that is summarized by the Panel. + * + *

+ * For example, for the connectivity panel you would intent to the Network & Internet page. + *

+ */ + Intent getSeeMoreIntent(); +} diff --git a/src/com/android/settings/panel/PanelFeatureProvider.java b/src/com/android/settings/panel/PanelFeatureProvider.java new file mode 100644 index 00000000000..7d6c5581d25 --- /dev/null +++ b/src/com/android/settings/panel/PanelFeatureProvider.java @@ -0,0 +1,27 @@ +/* + * 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.panel; + +import android.content.Context; + +public interface PanelFeatureProvider { + + /** + * Returns {@link PanelContent} as specified by the {@param panelType}. + */ + PanelContent getPanel(Context context, String panelType); +} diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java new file mode 100644 index 00000000000..2e840786b7f --- /dev/null +++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java @@ -0,0 +1,32 @@ +/* + * 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.panel; + +import android.content.Context; + +public class PanelFeatureProviderImpl implements PanelFeatureProvider { + + @Override + public PanelContent getPanel(Context context, String panelType) { + switch (panelType) { + case SettingsPanelActivity.PANEL_TYPE_WIFI: + return InternetConnectivityPanel.create(context); + } + + throw new IllegalStateException("No matching panel for: " + panelType); + } +} diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java new file mode 100644 index 00000000000..bbdaec351f4 --- /dev/null +++ b/src/com/android/settings/panel/PanelFragment.java @@ -0,0 +1,88 @@ +/* + * 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.panel; + +import android.net.Uri; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import android.widget.LinearLayout; + +import androidx.lifecycle.LiveData; +import androidx.slice.Slice; +import androidx.slice.widget.SliceLiveData; +import androidx.slice.widget.SliceView; + +import com.android.settings.R; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; + +import com.android.settings.overlay.FeatureFactory; + +import java.util.ArrayList; +import java.util.List; + +public class PanelFragment extends Fragment { + + private static final String TAG = "PanelFragment"; + + private List mSliceViewList; + private List> mSliceDataList; + private LinearLayout mPanelLayout; + + public PanelFragment() { + mSliceViewList = new ArrayList<>(); + mSliceDataList = new ArrayList<>(); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + final FragmentActivity activity = getActivity(); + final View view = inflater.inflate(R.layout.panel_layout, container, false); + + mPanelLayout = view.findViewById(R.id.panel_parent_layout); + final Bundle arguments = getArguments(); + + final String panelType = arguments.getString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT); + + final PanelContent panel = FeatureFactory.getFactory(activity) + .getPanelFeatureProvider() + .getPanel(activity, panelType); + + activity.setTitle(panel.getTitle()); + + + for (Uri uri : panel.getSlices()) { + final SliceView sliceView = new SliceView(activity); + mPanelLayout.addView(sliceView); + final LiveData liveData = SliceLiveData.fromUri(activity, uri); + liveData.observe(this /* lifecycleOwner */, sliceView); + + mSliceDataList.add(liveData); + mSliceViewList.add(sliceView); + } + + return view; + } +} diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java new file mode 100644 index 00000000000..db1f60d3e49 --- /dev/null +++ b/src/com/android/settings/panel/SettingsPanelActivity.java @@ -0,0 +1,103 @@ +/* + * 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.panel; + +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; + +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import com.android.settings.R; + +/** + * Dialog Activity to host Settings Slices. + * + * TODO link to action / framework API + */ +public class SettingsPanelActivity extends FragmentActivity { + + private final String TAG = "panel_activity"; + + /** + * Key specifying which Panel the app is requesting. + */ + public static final String KEY_PANEL_TYPE_ARGUMENT = "PANEL_TYPE_ARGUMENT"; + + + // TODO (b/117804442) move to framework + public static final String EXTRA_PANEL_TYPE = "com.android.settings.panel.extra"; + + // TODO (b/117804442) move to framework + public static final String PANEL_TYPE_WIFI = "wifi_panel"; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final ComponentName callingActivityName = getCallingActivity(); + + if (callingActivityName == null) { + Log.e(TAG, "Must start with startActivityForResult. Closing."); + finish(); + return; + } + + final Intent callingIntent = getIntent(); + if (callingIntent == null) { + Log.e(TAG, "Null intent, closing Panel Activity"); + finish(); + return; + } + + final String typeExtra = callingIntent.getStringExtra(EXTRA_PANEL_TYPE); + if (TextUtils.isEmpty(typeExtra)) { + Log.e(TAG, "No intent passed, closing Panel Activity"); + return; + } + + setContentView(R.layout.settings_panel); + + // Move the window to the bottom of screen, and make it take up the entire screen width. + final Window window = getWindow(); + window.setGravity(Gravity.BOTTOM); + window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.WRAP_CONTENT); + + + final Bundle bundle = new Bundle(); + bundle.putString(KEY_PANEL_TYPE_ARGUMENT, typeExtra); + + final PanelFragment panelFragment = new PanelFragment(); + panelFragment.setArguments(bundle); + + final FragmentManager fragmentManager = getSupportFragmentManager(); + final Fragment fragment = fragmentManager.findFragmentById(R.id.main_content); + if (fragment == null) { + fragmentManager.beginTransaction().add(R.id.main_content, panelFragment).commit(); + } + } +} diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index 14a918ed8f5..cbb35935871 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -19,8 +19,7 @@ package com.android.settings.password; import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD; import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD; -import static com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment - .RESULT_FINISHED; +import static com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Activity; @@ -77,12 +76,6 @@ public class ChooseLockGeneric extends SettingsActivity { public Intent getIntent() { Intent modIntent = new Intent(super.getIntent()); modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName()); - - String action = modIntent.getAction(); - if (ACTION_SET_NEW_PASSWORD.equals(action) - || ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) { - modIntent.putExtra(EXTRA_HIDE_DRAWER, true); - } return modIntent; } @@ -154,7 +147,6 @@ public class ChooseLockGeneric extends SettingsActivity { private FingerprintManager mFingerprintManager; private FaceManager mFaceManager; private int mUserId; - private boolean mHideDrawer = false; private ManagedLockPasswordProvider mManagedPasswordProvider; private boolean mIsSetNewPassword = false; private UserManager mUserManager; @@ -194,7 +186,6 @@ public class ChooseLockGeneric extends SettingsActivity { mUserPassword = getActivity().getIntent().getStringExtra( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); } - mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false); mHasChallenge = getActivity().getIntent().getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); @@ -345,7 +336,6 @@ public class ChooseLockGeneric extends SettingsActivity { mForFingerprint); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, mForFace); - intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); startActivityForResult( intent, mIsSetNewPassword && mHasChallenge @@ -748,9 +738,6 @@ public class ChooseLockGeneric extends SettingsActivity { } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { intent = getLockPatternIntent(); } - if (intent != null) { - intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); - } return intent; } diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index cd041933dcd..1ef95da036a 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -190,7 +190,6 @@ public class ChooseLockPassword extends SettingsActivity { private int mPasswordMinNonLetter = 0; private int mPasswordMinLengthToFulfillAllPolicies = 0; protected int mUserId; - private boolean mHideDrawer = false; private byte[] mPasswordHistoryHashFactor; /** * Password requirements that we need to verify. @@ -375,7 +374,6 @@ public class ChooseLockPassword extends SettingsActivity { mForFace = intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false); processPasswordRequirements(intent); mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity()); - mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false); if (intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) { @@ -975,7 +973,6 @@ public class ChooseLockPassword extends SettingsActivity { if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { - intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); startActivity(intent); } } diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java index 4e4730f73b4..0d06ed8292a 100644 --- a/src/com/android/settings/password/ChooseLockPattern.java +++ b/src/com/android/settings/password/ChooseLockPattern.java @@ -196,7 +196,6 @@ public class ChooseLockPattern extends SettingsActivity { private TextView mFooterLeftButton; private TextView mFooterRightButton; protected List mChosenPattern = null; - private boolean mHideDrawer = false; private ColorStateList mDefaultHeaderColorList; // ScrollView that contains title and header, only exist in land mode @@ -464,7 +463,6 @@ public class ChooseLockPattern extends SettingsActivity { w.start(mChooseLockSettingsHelper.utils(), required, false, 0, LockPatternUtils.stringToPattern(current), current, mUserId); } - mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false); mForFingerprint = intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); mForFace = intent.getBooleanExtra( @@ -808,7 +806,6 @@ public class ChooseLockPattern extends SettingsActivity { if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { - intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); startActivity(intent); } } diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java index d5182b30b02..938dec46f6c 100644 --- a/src/com/android/settings/password/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java @@ -391,8 +391,6 @@ public final class ChooseLockSettingsHelper { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, returnCredentials); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, hasChallenge); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); - // we should never have a drawer when confirming device credentials. - intent.putExtra(SettingsActivity.EXTRA_HIDE_DRAWER, true); intent.putExtra(Intent.EXTRA_USER_ID, userId); intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton); if (extras != null) { diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java index dd4c8fa03f5..91e85b3a3e6 100644 --- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java +++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java @@ -22,7 +22,10 @@ import android.provider.SearchIndexableResource; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.notification.LockScreenNotificationPreferenceController; import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; @@ -31,6 +34,11 @@ import java.util.List; @SearchIndexable public class PrivacyDashboardFragment extends DashboardFragment { private static final String TAG = "PrivacyDashboardFragment"; + private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "privacy_lock_screen_notifications"; + private static final String KEY_WORK_PROFILE_CATEGORY = + "privacy_work_profile_notifications_category"; + private static final String KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS = + "privacy_lock_screen_work_profile_notifications"; @Override public int getMetricsCategory() { @@ -52,6 +60,28 @@ public class PrivacyDashboardFragment extends DashboardFragment { return R.string.help_url_privacy_dashboard; } + @Override + protected List createPreferenceControllers(Context context) { + return buildPreferenceControllers(context, getSettingsLifecycle()); + } + + private static List buildPreferenceControllers( + Context context, Lifecycle lifecycle) { + final List controllers = new ArrayList<>(); + final LockScreenNotificationPreferenceController notificationController = + new LockScreenNotificationPreferenceController(context, + KEY_LOCK_SCREEN_NOTIFICATIONS, + KEY_WORK_PROFILE_CATEGORY, + KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS); + if (lifecycle != null) { + lifecycle.addObserver(notificationController); + } + controllers.add(notificationController); + + return controllers; + + } + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override @@ -64,5 +94,11 @@ public class PrivacyDashboardFragment extends DashboardFragment { result.add(sir); return result; } + + @Override + public List createPreferenceControllers( + Context context) { + return buildPreferenceControllers(context, null); + } }; } diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index fa669bb451a..952fc8b4596 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -427,7 +427,7 @@ public class SettingsSliceProvider extends SliceProvider { try { sliceData = mSlicesDatabaseAccessor.getSliceDataFromUri(uri); } catch (IllegalStateException e) { - Log.d(TAG, "Could not create slicedata for uri: " + uri); + Log.d(TAG, "Could not create slicedata for uri: " + uri, e); return; } diff --git a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java index 39d385eb9d4..508eb1c1d78 100644 --- a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java +++ b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java @@ -1,3 +1,19 @@ +/* + * 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.slices; import android.content.Context; diff --git a/src/com/android/settings/widget/EntityHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java index 267838cc0a9..056f6b46f88 100644 --- a/src/com/android/settings/widget/EntityHeaderController.java +++ b/src/com/android/settings/widget/EntityHeaderController.java @@ -16,8 +16,7 @@ package com.android.settings.widget; -import static com.android.internal.logging.nano.MetricsProto.MetricsEvent - .ACTION_OPEN_APP_NOTIFICATION_SETTING; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_OPEN_APP_NOTIFICATION_SETTING; import android.annotation.IdRes; import android.annotation.UserIdInt; @@ -48,11 +47,11 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.applications.AppInfoBase; -import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.appinfo.AppInfoDashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/src/com/android/settings/widget/TwoStateButtonPreference.java b/src/com/android/settings/widget/TwoStateButtonPreference.java index b154fb4193c..eeee65def8a 100644 --- a/src/com/android/settings/widget/TwoStateButtonPreference.java +++ b/src/com/android/settings/widget/TwoStateButtonPreference.java @@ -26,7 +26,7 @@ import androidx.annotation.VisibleForTesting; import androidx.core.content.res.TypedArrayUtils; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; +import com.android.settingslib.widget.LayoutPreference; /** * Preference that presents a button with two states(On vs Off) diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java index 3bf38a773ae..9a3398ad94f 100644 --- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java @@ -54,7 +54,6 @@ import androidx.preference.PreferenceScreen; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.Utils; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.EntityHeaderController; @@ -68,6 +67,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; +import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.wifi.AccessPoint; import java.net.Inet4Address; diff --git a/tests/robotests/assets/grandfather_not_implementing_instrumentable b/tests/robotests/assets/grandfather_not_implementing_instrumentable index 625d9ffecf2..04ef0ef9594 100644 --- a/tests/robotests/assets/grandfather_not_implementing_instrumentable +++ b/tests/robotests/assets/grandfather_not_implementing_instrumentable @@ -6,4 +6,5 @@ com.android.settings.password.ChooseLockPattern$SaveAndFinishWorker com.android.settings.RestrictedListPreference$RestrictedListPreferenceDialogFragment com.android.settings.password.ConfirmDeviceCredentialBaseFragment$LastTryDialog com.android.settings.password.CredentialCheckResultTracker -com.android.settings.dashboard.profileselector.ProfileSelectDialog \ No newline at end of file +com.android.settings.dashboard.profileselector.ProfileSelectDialog +com.android.settings.panel.PanelFragment \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/SettingsPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/SettingsPreferenceFragmentTest.java index 2fc3dcb1297..76f70433b48 100644 --- a/tests/robotests/src/com/android/settings/SettingsPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/SettingsPreferenceFragmentTest.java @@ -18,8 +18,10 @@ package com.android.settings; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; 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; @@ -37,6 +39,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settings.widget.WorkOnlyCategory; import org.junit.Before; import org.junit.Test; @@ -174,6 +177,20 @@ public class SettingsPreferenceFragmentTest { // no crash } + @Test + public void checkAvailablePrefs_selfAvialbalePreferenceNotAvailable_shouldHidePreference() { + doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); + final WorkOnlyCategory workOnlyCategory = mock(WorkOnlyCategory.class); + when(mPreferenceScreen.getPreferenceCount()).thenReturn(1); + when(mPreferenceScreen.getPreference(0)).thenReturn(workOnlyCategory); + when(workOnlyCategory.isAvailable(any(Context.class))).thenReturn(false); + + mFragment.checkAvailablePrefs(mPreferenceScreen); + + verify(mPreferenceScreen, never()).removePreference(workOnlyCategory); + verify(workOnlyCategory).setVisible(false); + } + public static class TestFragment extends SettingsPreferenceFragment { @Override diff --git a/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java index 19a140c5b0f..aeb5f547696 100644 --- a/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java @@ -35,11 +35,11 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.accounts.AuthenticatorHelper; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java index 3bebd66e08c..83ea2184910 100644 --- a/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java @@ -51,12 +51,12 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowAccountManager; import com.android.settings.testutils.shadow.ShadowContentResolver; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowUserManager; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java index ddcbf85e49f..3031f5b1a0f 100644 --- a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java +++ b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java @@ -44,6 +44,7 @@ import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.instantapps.InstantAppDataProvider; +import com.android.settingslib.widget.LayoutPreference; import org.junit.After; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/applications/LayoutPreferenceTest.java b/tests/robotests/src/com/android/settings/applications/LayoutPreferenceTest.java deleted file mode 100644 index 899d4cb650f..00000000000 --- a/tests/robotests/src/com/android/settings/applications/LayoutPreferenceTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2017 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.applications; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import android.content.Context; -import android.view.LayoutInflater; - -import androidx.preference.Preference.OnPreferenceClickListener; -import androidx.preference.PreferenceViewHolder; - -import com.android.settings.R; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; - -@RunWith(SettingsRobolectricTestRunner.class) -public class LayoutPreferenceTest { - - private Context mContext; - private LayoutPreference mPreference; - private PreferenceViewHolder mHolder; - - @Before - public void setUp() { - mContext = RuntimeEnvironment.application; - mPreference = new LayoutPreference(mContext, R.layout.two_action_buttons); - mHolder = PreferenceViewHolder.createInstanceForTests(LayoutInflater.from(mContext) - .inflate(R.layout.layout_preference_frame, null, false)); - } - - @Test - public void setOnClickListener_shouldAttachToRootView() { - final OnPreferenceClickListener listener = mock(OnPreferenceClickListener.class); - - mPreference.setOnPreferenceClickListener(listener); - mPreference.onBindViewHolder(mHolder); - - mHolder.itemView.callOnClick(); - - verify(listener).onPreferenceClick(mPreference); - assertThat(mHolder.itemView.isFocusable()).isTrue(); - assertThat(mHolder.itemView.isClickable()).isTrue(); - } - - @Test - public void setNonSelectable_viewShouldNotBeSelectable() { - mPreference.setSelectable(false); - mPreference.onBindViewHolder(mHolder); - - assertThat(mHolder.itemView.isFocusable()).isFalse(); - assertThat(mHolder.itemView.isClickable()).isFalse(); - } - - @Test - public void disableSomeView_shouldMaintainStateAfterBind() { - mPreference.findViewById(R.id.button1).setEnabled(false); - mPreference.findViewById(R.id.button2).setEnabled(true); - - mPreference.onBindViewHolder(mHolder); - - assertThat(mPreference.findViewById(R.id.button1).isEnabled()).isFalse(); - assertThat(mPreference.findViewById(R.id.button2).isEnabled()).isTrue(); - } - - @Test - public void allowDividerBelow_shouldSaveCorrectDividerStatus() { - mPreference.setAllowDividerBelow(true); - - assertThat(mPreference.isAllowDividerBelow()).isTrue(); - } -} diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java index d3e00c37159..67702f1dc42 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java @@ -42,10 +42,10 @@ import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java index 5d8c8426465..6879b7de2f3 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java @@ -48,11 +48,11 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.instantapps.InstantAppDataProvider; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java index 0430e0f4e5b..e62e338bcc5 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java @@ -33,7 +33,6 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice; @@ -41,6 +40,7 @@ import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.widget.LayoutPreference; import org.junit.After; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java index ec697ad4b66..2aa38d7188f 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java @@ -31,12 +31,12 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.testutils.DrawableTestHelper; +import com.android.settingslib.widget.LayoutPreference; import org.junit.After; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java index 3aae145c55c..859912aa71c 100644 --- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java @@ -34,10 +34,10 @@ import androidx.preference.PreferenceScreen; import com.android.internal.app.ColorDisplayController; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settingslib.widget.CandidateInfo; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java index 30dedb6a001..84d184de419 100644 --- a/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/NightDisplayActivationPreferenceControllerTest.java @@ -26,9 +26,9 @@ import android.view.View; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/dream/StartNowPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/StartNowPreferenceControllerTest.java index fc7edc2827c..21cb9f153fc 100644 --- a/tests/robotests/src/com/android/settings/dream/StartNowPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/dream/StartNowPreferenceControllerTest.java @@ -28,9 +28,9 @@ import android.widget.Button; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.dream.DreamBackend; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java index 1a8d58dff09..c9086abf773 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java @@ -51,7 +51,6 @@ import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.R; import com.android.settings.SettingsActivity; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowActivityManager; @@ -61,6 +60,7 @@ import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.instantapps.InstantAppDataProvider; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; import org.junit.After; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java index 5541654bc53..7797a786e57 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java @@ -42,7 +42,6 @@ import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; @@ -50,6 +49,7 @@ import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; import org.junit.After; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java index cf1a5f346d7..14caf2c8187 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -48,12 +48,12 @@ import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.R; import com.android.settings.SettingsActivity; -import com.android.settings.applications.LayoutPreference; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.XmlTestUtils; import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.BeforeClass; diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index f9eda497cb2..e8cb67474bb 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -40,7 +40,6 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowContentResolver; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -60,17 +59,6 @@ public class ContextualCardLoaderTest { mProvider); } - @Test - public void createStaticCards_shouldContainCorrectCards() { - final Uri batteryInfo = BatterySlice.BATTERY_CARD_URI; - final List expectedUris = Arrays.asList(batteryInfo); - - final List actualCardUris = mContextualCardLoader.createStaticCards().stream().map( - ContextualCard::getSliceUri).collect(Collectors.toList()); - - assertThat(actualCardUris).containsExactlyElementsIn(expectedUris); - } - @Test public void isCardEligibleToDisplay_customCard_returnTrue() { final ContextualCard customCard = new ContextualCard.Builder() @@ -224,4 +212,4 @@ public class ContextualCardLoaderTest { .build()); return cards; } -} +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardControllerTest.java index ab82a543f93..688e94cb550 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardControllerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardControllerTest.java @@ -16,6 +16,8 @@ package com.android.settings.homepage.contextualcards.conditional; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -25,6 +27,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.ContextualCard.CardType; import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener; import com.android.settings.testutils.SettingsRobolectricTestRunner; @@ -38,6 +41,7 @@ import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; +import java.util.Map; @RunWith(SettingsRobolectricTestRunner.class) public class ConditionContextualCardControllerTest { @@ -95,4 +99,81 @@ public class ConditionContextualCardControllerTest { verify(mListener, never()).onContextualCardUpdated(any()); } + + @Test + public void getConditionalCards_hasEmptyConditionCards_shouldReturnThreeEmptyList() { + final Map> conditionalCards = + mController.buildConditionalCardsWithFooterOrHeader(generateConditionCards(0)); + + assertThat(conditionalCards).hasSize(3); + for (@CardType int cardType : conditionalCards.keySet()) { + assertThat(conditionalCards.get(cardType)).isEmpty(); + } + } + + @Test + public void getConditionalCards_hasOneConditionCard_shouldGetOneFullWidthCard() { + final Map> conditionalCards = + mController.buildConditionalCardsWithFooterOrHeader(generateConditionCards(1)); + + assertThat(conditionalCards).hasSize(3); + assertThat(conditionalCards.get(CardType.CONDITIONAL)).hasSize(1); + assertThat(conditionalCards.get(CardType.CONDITIONAL).get(0).isHalfWidth()).isFalse(); + assertThat(conditionalCards.get(CardType.CONDITIONAL_HEADER)).isEmpty(); + assertThat(conditionalCards.get(CardType.CONDITIONAL_FOOTER)).isEmpty(); + } + + @Test + public void getConditionalCards_hasTwoConditionCards_shouldGetTwoHalfWidthCards() { + final Map> conditionalCards = + mController.buildConditionalCardsWithFooterOrHeader(generateConditionCards(2)); + + assertThat(conditionalCards).hasSize(3); + assertThat(conditionalCards.get(CardType.CONDITIONAL)).hasSize(2); + for (ContextualCard card : conditionalCards.get(CardType.CONDITIONAL)) { + assertThat(card.isHalfWidth()).isTrue(); + } + assertThat(conditionalCards.get(CardType.CONDITIONAL_HEADER)).isEmpty(); + assertThat(conditionalCards.get(CardType.CONDITIONAL_FOOTER)).isEmpty(); + } + + @Test + public void getConditionalCards_hasThreeCardsAndExpanded_shouldGetThreeCardsWithFooter() { + mController.setIsExpanded(true); + final Map> conditionalCards = + mController.buildConditionalCardsWithFooterOrHeader(generateConditionCards(3)); + + assertThat(conditionalCards).hasSize(3); + assertThat(conditionalCards.get(CardType.CONDITIONAL)).hasSize(3); + assertThat(conditionalCards.get(CardType.CONDITIONAL_HEADER)).isEmpty(); + assertThat(conditionalCards.get(CardType.CONDITIONAL_FOOTER)).isNotEmpty(); + } + + @Test + public void getConditionalCards_hasThreeCardsAndCollapsed_shouldGetOneConditionalHeader() { + mController.setIsExpanded(false); + final Map> conditionalCards = + mController.buildConditionalCardsWithFooterOrHeader(generateConditionCards(3)); + + assertThat(conditionalCards).hasSize(3); + assertThat(conditionalCards.get(CardType.CONDITIONAL)).isEmpty(); + assertThat(conditionalCards.get(CardType.CONDITIONAL_HEADER)).isNotEmpty(); + assertThat(conditionalCards.get(CardType.CONDITIONAL_FOOTER)).isEmpty(); + } + + private List generateConditionCards(int numberOfCondition) { + final List conditionCards = new ArrayList<>(); + for (int i = 0; i < numberOfCondition; i++) { + conditionCards.add(new ConditionalContextualCard.Builder() + .setConditionId(123 + i) + .setMetricsConstant(1) + .setActionText("test_action" + i) + .setName("test_name" + i) + .setTitleText("test_title" + i) + .setSummaryText("test_summary" + i) + .setIsHalfWidth(true) + .build()); + } + return conditionCards; + } } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardRendererTest.java new file mode 100644 index 00000000000..524a69091da --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardRendererTest.java @@ -0,0 +1,101 @@ +/* + * 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.contextualcards.conditional; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.ControllerRendererPool; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +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; + +@RunWith(SettingsRobolectricTestRunner.class) +public class ConditionFooterContextualCardRendererTest { + + @Mock + private ControllerRendererPool mControllerRendererPool; + @Mock + private ConditionContextualCardController mController; + private Context mContext; + private ConditionFooterContextualCardRenderer mRenderer; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mRenderer = new ConditionFooterContextualCardRenderer(mContext, mControllerRendererPool); + } + + @Test + public void bindView_shouldSetClickListener() { + final int viewType = mRenderer.getViewType(false /* isHalfWidth */); + final RecyclerView recyclerView = new RecyclerView(mContext); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false); + final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); + when(mControllerRendererPool.getController(mContext, + ContextualCard.CardType.CONDITIONAL_FOOTER)).thenReturn(mController); + + mRenderer.bindView(viewHolder, generateConditionFooterContextualCard()); + + assertThat(viewHolder.itemView).isNotNull(); + assertThat(viewHolder.itemView.hasOnClickListeners()).isTrue(); + } + + @Test + public void bindView_clickView_shouldSetTrueToIsConditionExpanded() { + final int viewType = mRenderer.getViewType(false /* isHalfWidth */); + final RecyclerView recyclerView = new RecyclerView(mContext); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false); + final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); + when(mControllerRendererPool.getController(mContext, + ContextualCard.CardType.CONDITIONAL_FOOTER)).thenReturn(mController); + + mRenderer.bindView(viewHolder, generateConditionFooterContextualCard()); + + assertThat(viewHolder.itemView).isNotNull(); + viewHolder.itemView.performClick(); + + verify(mController).setIsExpanded(false); + verify(mController).onConditionsChanged(); + } + + private ContextualCard generateConditionFooterContextualCard() { + return new ConditionFooterContextualCard.Builder() + .setName("test_condition_footer") + .setRankingScore(-9999.0) + .build(); + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardTest.java new file mode 100644 index 00000000000..783ae9f1e7a --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionFooterContextualCardTest.java @@ -0,0 +1,42 @@ +/* + * 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.contextualcards.conditional; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(SettingsRobolectricTestRunner.class) +public class ConditionFooterContextualCardTest { + + @Test(expected = IllegalArgumentException.class) + public void newInstance_changeCardType_shouldCrash() { + new ConditionFooterContextualCard.Builder() + .setCardType(ContextualCard.CardType.LEGACY_SUGGESTION) + .build(); + } + + @Test + public void getCardType_shouldAlwaysBeConditionalFooter() { + assertThat(new ConditionFooterContextualCard.Builder().build().getCardType()) + .isEqualTo(ContextualCard.CardType.CONDITIONAL_FOOTER); + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java new file mode 100644 index 00000000000..dbe554426b5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java @@ -0,0 +1,121 @@ +/* + * 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.contextualcards.conditional; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.ControllerRendererPool; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +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 java.util.ArrayList; +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +public class ConditionHeaderContextualCardRendererTest { + + @Mock + private ControllerRendererPool mControllerRendererPool; + @Mock + private ConditionContextualCardController mController; + private Context mContext; + private ConditionHeaderContextualCardRenderer mRenderer; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mRenderer = new ConditionHeaderContextualCardRenderer(mContext, mControllerRendererPool); + } + + @Test + public void bindView_shouldSetClickListener() { + final int viewType = mRenderer.getViewType(false /* isHalfWidth */); + final RecyclerView recyclerView = new RecyclerView(mContext); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false); + final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); + when(mControllerRendererPool.getController(mContext, + ContextualCard.CardType.CONDITIONAL_HEADER)).thenReturn(mController); + + mRenderer.bindView(viewHolder, generateConditionHeaderContextualCard()); + + assertThat(viewHolder.itemView).isNotNull(); + assertThat(viewHolder.itemView.hasOnClickListeners()).isTrue(); + } + + @Test + public void bindView_clickView_shouldSetTrueToIsConditionExpanded() { + final int viewType = mRenderer.getViewType(false /* isHalfWidth */); + final RecyclerView recyclerView = new RecyclerView(mContext); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false); + final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); + when(mControllerRendererPool.getController(mContext, + ContextualCard.CardType.CONDITIONAL_HEADER)).thenReturn(mController); + + mRenderer.bindView(viewHolder, generateConditionHeaderContextualCard()); + + assertThat(viewHolder.itemView).isNotNull(); + viewHolder.itemView.performClick(); + + verify(mController).setIsExpanded(true); + verify(mController).onConditionsChanged(); + } + + private ContextualCard generateConditionHeaderContextualCard() { + return new ConditionHeaderContextualCard.Builder() + .setConditionalCards(generateConditionCards(3)) + .setName("test_condition_header") + .setRankingScore(-9999.0) + .build(); + } + + private List generateConditionCards(int numberOfCondition) { + final List conditionCards = new ArrayList<>(); + for (int i = 0; i < numberOfCondition; i++) { + conditionCards.add(new ConditionalContextualCard.Builder() + .setConditionId(123 + i) + .setMetricsConstant(1) + .setActionText("test_action" + i) + .setName("test_name" + i) + .setTitleText("test_title" + i) + .setSummaryText("test_summary" + i) + .setIsHalfWidth(true) + .build()); + } + return conditionCards; + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardTest.java new file mode 100644 index 00000000000..767adad66dd --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardTest.java @@ -0,0 +1,42 @@ +/* + * 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.contextualcards.conditional; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(SettingsRobolectricTestRunner.class) +public class ConditionHeaderContextualCardTest { + + @Test(expected = IllegalArgumentException.class) + public void newInstance_changeCardType_shouldCrash() { + new ConditionHeaderContextualCard.Builder() + .setCardType(ContextualCard.CardType.LEGACY_SUGGESTION) + .build(); + } + + @Test + public void getCardType_shouldAlwaysBeConditionalHeader() { + assertThat(new ConditionHeaderContextualCard.Builder().build().getCardType()) + .isEqualTo(ContextualCard.CardType.CONDITIONAL_HEADER); + } +} diff --git a/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java index 91a545c595d..46d177f88a9 100644 --- a/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java @@ -187,11 +187,4 @@ public class AirplaneModePreferenceControllerTest { new AirplaneModePreferenceController(mContext,"toggle_airplane"); assertThat(controller.isSliceable()).isTrue(); } - - @Test - public void isSliceableIncorrectKey_returnsFalse() { - final AirplaneModePreferenceController controller = - new AirplaneModePreferenceController(mContext, "bad_key"); - assertThat(controller.isSliceable()).isFalse(); - } } diff --git a/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java index 06ef6010c1a..0ebcaefa435 100644 --- a/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java @@ -45,9 +45,9 @@ import android.content.Context; import android.os.UserManager; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.widget.SwitchBar; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java index 57c87129926..04dac267086 100644 --- a/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java @@ -37,7 +37,7 @@ import android.view.View; import androidx.fragment.app.FragmentActivity; import androidx.preference.PreferenceFragmentCompat; -import com.android.settings.applications.LayoutPreference; +import com.android.settingslib.widget.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java new file mode 100644 index 00000000000..3e210f5298c --- /dev/null +++ b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java @@ -0,0 +1,52 @@ +/* + * 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.panel; + +import static com.google.common.truth.Truth.assertThat; + +import android.net.Uri; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.wifi.WifiSlice; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; + +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) + +public class InternetConnectivityPanelTest { + + private InternetConnectivityPanel mPanel; + + @Before + public void setUp() { + mPanel = InternetConnectivityPanel.create(RuntimeEnvironment.application); + } + + @Test + public void getSlices_containsNecessarySlices() { + final List uris = mPanel.getSlices(); + + assertThat(uris).containsExactly(WifiSlice.WIFI_URI, + InternetConnectivityPanel.AIRPLANE_URI); + } +} diff --git a/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java new file mode 100644 index 00000000000..050fd0cd899 --- /dev/null +++ b/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java @@ -0,0 +1,52 @@ +/* + * 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.panel; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class PanelFeatureProviderImplTest { + + private Context mContext; + private PanelFeatureProviderImpl mProvider; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mProvider = new PanelFeatureProviderImpl(); + } + + @Test + public void getPanel_internetConnectivityKey_returnsCorrectPanel() { + final PanelContent panel = mProvider.getPanel(mContext, + SettingsPanelActivity.PANEL_TYPE_WIFI); + + assertThat(panel).isInstanceOf(InternetConnectivityPanel.class); + } + +} diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java index 24db8298c80..e14ef1f4b9d 100644 --- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -33,6 +33,7 @@ import com.android.settings.overlay.DockUpdaterFeatureProvider; import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.SupportFeatureProvider; import com.android.settings.overlay.SurveyFeatureProvider; +import com.android.settings.panel.PanelFeatureProvider; import com.android.settings.search.SearchFeatureProvider; import com.android.settings.security.SecurityFeatureProvider; import com.android.settings.slices.SlicesFeatureProvider; @@ -61,6 +62,7 @@ public class FakeFeatureFactory extends FeatureFactory { public final UserFeatureProvider userFeatureProvider; public final AssistGestureFeatureProvider assistGestureFeatureProvider; public final AccountFeatureProvider mAccountFeatureProvider; + public final PanelFeatureProvider mPanelFeatureProvider; public SlicesFeatureProvider slicesFeatureProvider; public SearchFeatureProvider searchFeatureProvider; @@ -102,6 +104,7 @@ public class FakeFeatureFactory extends FeatureFactory { assistGestureFeatureProvider = mock(AssistGestureFeatureProvider.class); slicesFeatureProvider = mock(SlicesFeatureProvider.class); mAccountFeatureProvider = mock(AccountFeatureProvider.class); + mPanelFeatureProvider = mock(PanelFeatureProvider.class); } @Override @@ -183,4 +186,9 @@ public class FakeFeatureFactory extends FeatureFactory { public AccountFeatureProvider getAccountFeatureProvider() { return mAccountFeatureProvider; } + + @Override + public PanelFeatureProvider getPanelFeatureProvider() { + return mPanelFeatureProvider; + } } diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java index 5e5410ce0cd..9417e9c9341 100644 --- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java +++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java @@ -83,6 +83,8 @@ public class SettingsRobolectricTestRunner extends RobolectricTestRunner { Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/RestrictedLockUtils/res/")), null)); paths.add(new ResourcePath(null, Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SearchWidget/res/")), null)); + paths.add(new ResourcePath(null, + Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SettingsLayoutPreference/res")), null)); paths.add(new ResourcePath(null, Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null)); paths.add(new ResourcePath(null, diff --git a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java index 5d608106272..56395493483 100644 --- a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java @@ -46,10 +46,10 @@ import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.ShadowIconDrawableFactory; import com.android.settingslib.applications.ApplicationsState; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java index 59e6287e074..4a0988a25c9 100644 --- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java @@ -62,7 +62,6 @@ import androidx.preference.PreferenceScreen; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; -import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowBidiFormatter; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; @@ -73,6 +72,7 @@ import com.android.settings.widget.EntityHeaderController; import com.android.settings.wifi.WifiDetailPreference; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.wifi.AccessPoint; import org.junit.Before;